Jogamp
GLJPanel: Allow reconfiguration of offscreen's GLCapabilitiesImmutable
authorSven Gothel <sgothel@jausoft.com>
Sat, 13 Sep 2014 23:14:38 +0000 (01:14 +0200)
committerSven Gothel <sgothel@jausoft.com>
Sat, 13 Sep 2014 23:21:19 +0000 (01:21 +0200)
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'

src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/TestGearsES2GLJPanelAWT.java
src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/TestGearsGLJPanelAWT.java

index ee1ac5f..baa85ca 100644 (file)
@@ -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.
+   * <p>
+   * 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.
+   * </p>
+   * <p>
+   * Method will dispose a previous {@link #isRealized() realized} GLContext and offscreen backend!
+   * </p>
+   * @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 {
index dd16b88..9841bb3 100644 (file)
@@ -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);
index 3650e49..f47a9b7 100644 (file)
@@ -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;
http://JogAmp.org git info: FAQ, tutorial and man pages.