aboutsummaryrefslogtreecommitdiffstats
path: root/src/jogl/classes/javax/media/opengl
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2013-09-08 03:02:36 +0200
committerSven Gothel <[email protected]>2013-09-08 03:02:36 +0200
commit76048cd784ea6df32f19e97bb228e4ead880ea07 (patch)
tree38f86d539cfd27d8f784f767b00904342b9b42b3 /src/jogl/classes/javax/media/opengl
parent9b5cee85c299e72735bebbfea5c23d3c71bc704e (diff)
Test: Don't resize frame, tweek print-matrix; AWTPrintLifecycle: Add scale and convenient AWT container traversal context; GLCanvas/GLJPanel properly handle existing MSAA and req. AA;
- Test: Don't resize frame, tweek print-matrix - Use scaleComp72 to scale the frame to fit on page, i.e. global print matrix - Use scaleGLMatXY = 72.0 / glDPI to locally scale on the GL drawable as being passed to AWTPrintLifecycle.setup(..) - Hence frame stays untouched/stable, no need for 'offscreen' print test, which is removed. - AWTPrintLifecycle: Add scale and convenient AWT container traversal context Use a simple decoration for all AWTPrintLifecycle impl. components within a container: final AWTPrintLifecycle.Context ctx = AWTPrintLifecycle.Context.setupPrint(frame, g2d, scaleGLMatXY, scaleGLMatXY); try { } finally { ctx.releasePrint(); } - GLCanvas/GLJPanel properly handle existing MSAA and req. AA; - GLCanvas: Workaround bug where onscreen MSAA cannot switch to offscreen FBO, i.e. stay 'onscreen' - GLJPanel: Use new offscreen FBO if MSAA is requested and not yet used. - GLJPanel.Offscreen.postGL(): always swapBufer(), was missing for !GLSL swapping Results GLCanvas / GLJPanel: - Good scaling - Stable behavior / visibility - High DPI mode works
Diffstat (limited to 'src/jogl/classes/javax/media/opengl')
-rw-r--r--src/jogl/classes/javax/media/opengl/awt/AWTPrintLifecycle.java49
-rw-r--r--src/jogl/classes/javax/media/opengl/awt/GLCanvas.java85
-rw-r--r--src/jogl/classes/javax/media/opengl/awt/GLJPanel.java121
3 files changed, 183 insertions, 72 deletions
diff --git a/src/jogl/classes/javax/media/opengl/awt/AWTPrintLifecycle.java b/src/jogl/classes/javax/media/opengl/awt/AWTPrintLifecycle.java
index 077ee42a9..293bdb809 100644
--- a/src/jogl/classes/javax/media/opengl/awt/AWTPrintLifecycle.java
+++ b/src/jogl/classes/javax/media/opengl/awt/AWTPrintLifecycle.java
@@ -29,9 +29,12 @@ package javax.media.opengl.awt;
import javax.media.opengl.GLAutoDrawable;
import java.awt.Component;
+import java.awt.Container;
import java.awt.Graphics;
import java.awt.Graphics2D;
+import jogamp.nativewindow.awt.AWTMisc;
+
/**
* Interface describing print lifecycle to support AWT printing
* on AWT {@link GLAutoDrawable}s.
@@ -41,11 +44,55 @@ public interface AWTPrintLifecycle {
/**
* Shall be called before {@link Component#print(Graphics)}.
* @param g2d the {@link Graphics2D} instance, which will be used for printing.
+ * @param scaleMatX {@link Graphics2D} {@link Graphics2D#scale(double, double) scaling factor}, i.e. rendering 1/scaleMatX * width pixels
+ * @param scaleMatY {@link Graphics2D} {@link Graphics2D#scale(double, double) scaling factor}, i.e. rendering 1/scaleMatY * height pixels
*/
- void setupPrint(Graphics2D g2d);
+ void setupPrint(Graphics2D g2d, double scaleMatX, double scaleMatY);
/**
* Shall be called after very last {@link Component#print(Graphics)}.
*/
void releasePrint();
+
+ public static class Context {
+ public static Context setupPrint(Container c, Graphics2D g2d, double scaleMatX, double scaleMatY) {
+ final Context t = new Context(c, g2d, scaleMatX, scaleMatY);
+ t.setupPrint(c);
+ return t;
+ }
+
+ public void releasePrint() {
+ count = AWTMisc.performAction(cont, AWTPrintLifecycle.class, releaseAction);
+ }
+
+ public int getCount() { return count; }
+
+ private final Container cont;
+ private final Graphics2D g2d;
+ private final double scaleMatX;
+ private final double scaleMatY;
+ private int count;
+
+ private final AWTMisc.ComponentAction setupAction = new AWTMisc.ComponentAction() {
+ @Override
+ public void run(Component c) {
+ ((AWTPrintLifecycle)c).setupPrint(g2d, scaleMatX, scaleMatY);
+ } };
+ private final AWTMisc.ComponentAction releaseAction = new AWTMisc.ComponentAction() {
+ @Override
+ public void run(Component c) {
+ ((AWTPrintLifecycle)c).releasePrint();
+ } };
+
+ private Context(Container c, Graphics2D g2d, double scaleMatX, double scaleMatY) {
+ this.cont = c;
+ this.g2d = g2d;
+ this.scaleMatX = scaleMatX;
+ this.scaleMatY = scaleMatY;
+ this.count = 0;
+ }
+ private void setupPrint(Container c) {
+ count = AWTMisc.performAction(c, AWTPrintLifecycle.class, setupAction);
+ }
+ }
}
diff --git a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java
index 8f9684db1..b2ffc17a2 100644
--- a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java
+++ b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java
@@ -86,7 +86,6 @@ import javax.media.opengl.GLDrawable;
import javax.media.opengl.GLDrawableFactory;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.GLException;
-import javax.media.opengl.GLOffscreenAutoDrawable;
import javax.media.opengl.GLProfile;
import javax.media.opengl.GLRunnable;
import javax.media.opengl.Threading;
@@ -733,11 +732,11 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
private volatile boolean printActive = false;
private boolean printUseAA = false;
private GLAnimatorControl printAnimator = null;
- private GLOffscreenAutoDrawable printGLAD = null;
+ private GLAutoDrawable printGLAD = null;
private AWTTilePainter printAWTTiles = null;
@Override
- public void setupPrint(Graphics2D g2d) {
+ public void setupPrint(Graphics2D g2d, double scaleMatX, double scaleMatY) {
if( !validateGLDrawable() ) {
if(DEBUG) {
System.err.println(getThreadName()+": Info: GLCanvas setupPrint - skipped GL render, drawable not valid yet");
@@ -758,7 +757,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
printUseAA = null != _useAA && ( _useAA == RenderingHints.VALUE_ANTIALIAS_DEFAULT || _useAA == RenderingHints.VALUE_ANTIALIAS_ON );
}
if( DEBUG ) {
- System.err.println("AWT print.setup: canvasSize "+getWidth()+"x"+getWidth()+", useAA "+printUseAA+", printAnimator "+printAnimator);
+ System.err.println("AWT print.setup: canvasSize "+getWidth()+"x"+getWidth()+", scaleMat "+scaleMatX+" x "+scaleMatY+", useAA "+printUseAA+", printAnimator "+printAnimator);
{
final Set<Entry<Object, Object>> rEntries = rHints.entrySet();
int count = 0;
@@ -770,7 +769,10 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
final AffineTransform aTrans = g2d.getTransform();
System.err.println(" scale "+aTrans.getScaleX()+" x "+aTrans.getScaleY());
System.err.println(" move "+aTrans.getTranslateX()+" x "+aTrans.getTranslateY());
- }
+ }
+ final int componentCount = isOpaque() ? 3 : 4;
+ final TileRenderer printRenderer = new TileRenderer();
+ printAWTTiles = new AWTTilePainter(printRenderer, componentCount, scaleMatX, scaleMatY, DEBUG);
AWTEDTExecutor.singleton.invoke(getTreeLock(), true /* allowOnNonEDT */, true /* wait */, setupPrintOnEDT);
}
private final Runnable setupPrintOnEDT = new Runnable() {
@@ -782,30 +784,31 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
printAnimator.remove(GLCanvas.this);
}
final GLCapabilities caps = (GLCapabilities)getChosenGLCapabilities().cloneMutable();
- caps.setDoubleBuffered(false);
final GLProfile glp = caps.getGLProfile();
- if( printUseAA && !caps.getSampleBuffers() ) {
- if ( !glp.isGL2ES3() ) {
- if( DEBUG ) {
- System.err.println("Ignore MSAA due to gl-profile < GL2ES3");
+ if( caps.getSampleBuffers() ) {
+ // bug / issue w/ swapGLContextAndAllGLEventListener and onscreen MSAA w/ NV/GLX
+ printGLAD = GLCanvas.this;
+ } else {
+ caps.setDoubleBuffered(false);
+ caps.setOnscreen(false);
+ if( printUseAA && !caps.getSampleBuffers() ) {
+ if ( !glp.isGL2ES3() ) {
+ if( DEBUG ) {
+ System.err.println("Ignore MSAA due to gl-profile < GL2ES3");
+ }
+ printUseAA = false;
+ } else {
+ caps.setSampleBuffers(true);
+ caps.setNumSamples(8);
}
- printUseAA = false;
- } else {
- caps.setSampleBuffers(true);
- caps.setNumSamples(8); // FIXME
}
+ final GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile());
+ printGLAD = factory.createOffscreenAutoDrawable(null, caps, null, PRINT_TILE_SIZE, PRINT_TILE_SIZE, null);
+ GLDrawableUtil.swapGLContextAndAllGLEventListener(GLCanvas.this, printGLAD);
}
- caps.setOnscreen(false);
- final GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile());
- printGLAD = factory.createOffscreenAutoDrawable(null, caps, null, PRINT_TILE_SIZE, PRINT_TILE_SIZE, null);
- GLDrawableUtil.swapGLContextAndAllGLEventListener(GLCanvas.this, printGLAD);
- destroyOnEDTAction.run();
- final int componentCount = isOpaque() ? 3 : 4;
- final TileRenderer printRenderer = new TileRenderer();
- printRenderer.setTileSize(printGLAD.getWidth(), printGLAD.getHeight(), 0);
- printRenderer.attachToAutoDrawable(printGLAD);
- printAWTTiles = new AWTTilePainter(printRenderer, componentCount, DEBUG);
+ printAWTTiles.renderer.setTileSize(printGLAD.getWidth(), printGLAD.getHeight(), 0);
+ printAWTTiles.renderer.attachToAutoDrawable(printGLAD);
if( DEBUG ) {
System.err.println("AWT print.setup "+printAWTTiles);
System.err.println("AWT print.setup AA "+printUseAA+", "+caps);
@@ -832,9 +835,10 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
}
printAWTTiles.dispose();
printAWTTiles= null;
- createDrawableAndContext( false );
- GLDrawableUtil.swapGLContextAndAllGLEventListener(printGLAD, GLCanvas.this);
- printGLAD.destroy();
+ if( printGLAD != GLCanvas.this ) {
+ GLDrawableUtil.swapGLContextAndAllGLEventListener(printGLAD, GLCanvas.this);
+ printGLAD.destroy();
+ }
printGLAD = null;
if( null != printAnimator ) {
printAnimator.add(GLCanvas.this);
@@ -854,17 +858,26 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
// we cannot dispatch print on AWT-EDT due to printing internal locking ..
}
sendReshape = false; // clear reshape flag
- final Graphics2D printGraphics = (Graphics2D)graphics;
- printAWTTiles.updateGraphics2DAndClipBounds(printGraphics);
- final TileRenderer tileRenderer = printAWTTiles.getTileRenderer();
- if( DEBUG ) {
- System.err.println("AWT print.0: "+tileRenderer);
+
+ final Graphics2D g2d = (Graphics2D)graphics;
+ printAWTTiles.setupGraphics2DAndClipBounds(g2d);
+ try {
+ final TileRenderer tileRenderer = printAWTTiles.renderer;
+ if( DEBUG ) {
+ System.err.println("AWT print.0: "+tileRenderer);
+ }
+ do {
+ if( printGLAD != GLCanvas.this ) {
+ tileRenderer.display();
+ } else {
+ Threading.invoke(true, displayOnEDTAction, getTreeLock());
+ }
+ } while ( !tileRenderer.eot() );
+ } finally {
+ printAWTTiles.resetGraphics2D();
}
- do {
- tileRenderer.display();
- } while ( !tileRenderer.eot() );
if( DEBUG ) {
- System.err.println("AWT print.X: "+tileRenderer);
+ System.err.println("AWT print.X: "+printAWTTiles);
}
}
diff --git a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
index 2488bd443..b549ad30c 100644
--- a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
+++ b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
@@ -98,6 +98,7 @@ import com.jogamp.nativewindow.awt.AWTWindowClosingProtocol;
import com.jogamp.opengl.FBObject;
import com.jogamp.opengl.util.GLPixelBuffer.GLPixelAttributes;
import com.jogamp.opengl.util.GLPixelBuffer.SingletonGLPixelBufferProvider;
+import com.jogamp.opengl.util.GLDrawableUtil;
import com.jogamp.opengl.util.GLPixelStorageModes;
import com.jogamp.opengl.util.TileRenderer;
import com.jogamp.opengl.util.awt.AWTGLPixelBuffer;
@@ -500,12 +501,15 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
}
}
+ private static final int PRINT_TILE_SIZE = 512;
private volatile boolean printActive = false;
+ private boolean printUseAA = false;
private GLAnimatorControl printAnimator = null;
+ private GLAutoDrawable printGLAD = null;
private AWTTilePainter printAWTTiles = null;
@Override
- public void setupPrint(Graphics2D g2d) {
+ public void setupPrint(Graphics2D g2d, double scaleMatX, double scaleMatY) {
if (!isInitialized) {
if(DEBUG) {
System.err.println(getThreadName()+": Info: GLJPanel setupPrint - skipped GL render, drawable not valid yet");
@@ -521,6 +525,28 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
printActive = true;
sendReshape = false; // clear reshape flag
handleReshape = false; // ditto
+ final RenderingHints rHints = g2d.getRenderingHints();
+ {
+ final Object _useAA = rHints.get(RenderingHints.KEY_ANTIALIASING);
+ printUseAA = null != _useAA && ( _useAA == RenderingHints.VALUE_ANTIALIAS_DEFAULT || _useAA == RenderingHints.VALUE_ANTIALIAS_ON );
+ }
+ if( DEBUG ) {
+ System.err.println("AWT print.setup: canvasSize "+getWidth()+"x"+getWidth()+", scaleMat "+scaleMatX+" x "+scaleMatY+", useAA "+printUseAA+", printAnimator "+printAnimator);
+ {
+ final Set<Entry<Object, Object>> rEntries = rHints.entrySet();
+ int count = 0;
+ for(Iterator<Entry<Object, Object>> rEntryIter = rEntries.iterator(); rEntryIter.hasNext(); count++) {
+ final Entry<Object, Object> rEntry = rEntryIter.next();
+ System.err.println("Hint["+count+"]: "+rEntry.getKey()+" -> "+rEntry.getValue());
+ }
+ }
+ final AffineTransform aTrans = g2d.getTransform();
+ System.err.println(" scale "+aTrans.getScaleX()+" x "+aTrans.getScaleY());
+ System.err.println(" move "+aTrans.getTranslateX()+" x "+aTrans.getTranslateY());
+ }
+ final int componentCount = isOpaque() ? 3 : 4;
+ final TileRenderer printRenderer = new TileRenderer();
+ printAWTTiles = new AWTTilePainter(printRenderer, componentCount, scaleMatX, scaleMatY, DEBUG);
AWTEDTExecutor.singleton.invoke(getTreeLock(), true /* allowOnNonEDT */, true /* wait */, setupPrintOnEDT);
}
private final Runnable setupPrintOnEDT = new Runnable() {
@@ -531,14 +557,34 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
printAnimator = helper.getAnimator();
if( null != printAnimator ) {
printAnimator.remove(GLJPanel.this);
- }
- final int componentCount = isOpaque() ? 3 : 4;
- final TileRenderer printRenderer = new TileRenderer();
- printRenderer.setTileSize(getWidth(), getHeight(), 0);
- printRenderer.attachToAutoDrawable(GLJPanel.this);
- printAWTTiles = new AWTTilePainter(printRenderer, componentCount, DEBUG);
+ }
+
+ printGLAD = GLJPanel.this; // default: re-use
+ final GLCapabilities caps = (GLCapabilities)getChosenGLCapabilities().cloneMutable();
+ final GLProfile glp = caps.getGLProfile();
+ if( printUseAA && !caps.getSampleBuffers() ) {
+ if ( !glp.isGL2ES3() ) {
+ if( DEBUG ) {
+ System.err.println("Ignore MSAA due to gl-profile < GL2ES3");
+ }
+ printUseAA = false;
+ } else {
+ // MSAA FBO ..
+ caps.setDoubleBuffered(false);
+ caps.setOnscreen(false);
+ caps.setSampleBuffers(true);
+ caps.setNumSamples(8);
+ final GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile());
+ printGLAD = factory.createOffscreenAutoDrawable(null, caps, null, PRINT_TILE_SIZE, PRINT_TILE_SIZE, null);
+ GLDrawableUtil.swapGLContextAndAllGLEventListener(GLJPanel.this, printGLAD);
+ }
+ }
+ printAWTTiles.renderer.setTileSize(printGLAD.getWidth(), printGLAD.getHeight(), 0);
+ printAWTTiles.renderer.attachToAutoDrawable(printGLAD);
if( DEBUG ) {
System.err.println("AWT print.setup "+printAWTTiles);
+ System.err.println("AWT print.setup AA "+printUseAA+", "+caps);
+ System.err.println("AWT print.setup "+printGLAD);
}
}
};
@@ -563,6 +609,11 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
}
printAWTTiles.dispose();
printAWTTiles= null;
+ if( printGLAD != GLJPanel.this ) {
+ GLDrawableUtil.swapGLContextAndAllGLEventListener(printGLAD, GLJPanel.this);
+ printGLAD.destroy();
+ }
+ printGLAD = null;
if( null != printAnimator ) {
printAnimator.add(GLJPanel.this);
printAnimator = null;
@@ -582,33 +633,26 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
}
sendReshape = false; // clear reshape flag
handleReshape = false; // ditto
- final Graphics2D printGraphics = (Graphics2D)graphics;
- if( DEBUG ) {
- System.err.println("AWT print.0: canvasSize "+getWidth()+"x"+getWidth()+", printAnimator "+printAnimator);
- {
- final RenderingHints rHints = printGraphics.getRenderingHints();
- final Set<Entry<Object, Object>> rEntries = rHints.entrySet();
- int count = 0;
- for(Iterator<Entry<Object, Object>> rEntryIter = rEntries.iterator(); rEntryIter.hasNext(); count++) {
- final Entry<Object, Object> rEntry = rEntryIter.next();
- System.err.println("Hint["+count+"]: "+rEntry.getKey()+" -> "+rEntry.getValue());
- }
+
+ final Graphics2D g2d = (Graphics2D)graphics;
+ printAWTTiles.setupGraphics2DAndClipBounds(g2d);
+ try {
+ final TileRenderer tileRenderer = printAWTTiles.renderer;
+ if( DEBUG ) {
+ System.err.println("AWT print.0: "+tileRenderer);
}
- final AffineTransform aTrans = printGraphics.getTransform();
- System.err.println(" scale "+aTrans.getScaleX()+" x "+aTrans.getScaleY());
- System.err.println(" move "+aTrans.getTranslateX()+" x "+aTrans.getTranslateY());
- }
- printAWTTiles.updateGraphics2DAndClipBounds(printGraphics);
- final TileRenderer tileRenderer = printAWTTiles.getTileRenderer();
- if( DEBUG ) {
- System.err.println("AWT print.0: "+tileRenderer);
+ do {
+ if( printGLAD != GLJPanel.this ) {
+ tileRenderer.display();
+ } else {
+ backend.doPlainPaint();
+ }
+ } while ( !tileRenderer.eot() );
+ } finally {
+ printAWTTiles.resetGraphics2D();
}
- do {
- // printRenderer.display();
- backend.doPlainPaint();
- } while ( !tileRenderer.eot() );
if( DEBUG ) {
- System.err.println("AWT print.X: "+tileRenderer);
+ System.err.println("AWT print.X: "+printAWTTiles);
}
}
@Override
@@ -803,6 +847,12 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
// so swapping the buffers doesn't do anything. We also don't
// currently have the provision to skip copying the data to the
// Swing portion of the GLJPanel in any of the rendering paths.
+ if( printActive && isInitialized) {
+ final Backend b = backend;
+ if ( null != b ) {
+ b.getDrawable().swapBuffers();
+ }
+ }
}
@Override
@@ -1007,7 +1057,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
backend.postGL(g, true);
}
- public void print(GLAutoDrawable drawable) {
+ public void plainPaint(GLAutoDrawable drawable) {
helper.display(GLJPanel.this);
}
@@ -1066,7 +1116,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
private final Runnable updaterPlainDisplayAction = new Runnable() {
@Override
public void run() {
- updater.print(GLJPanel.this);
+ updater.plainPaint(GLJPanel.this);
}
};
@@ -1405,13 +1455,14 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
gl2es3.glPixelStorei(GL2ES3.GL_PACK_ROW_LENGTH, pixelBuffer.width);
gl2es3.glReadBuffer(gl2es3.getDefaultReadBuffer());
}
-
+
+ offscreenDrawable.swapBuffers();
+
if(null != glslTextureRaster) { // implies flippedVertical
// perform vert-flipping via OpenGL/FBO
final GLFBODrawable fboDrawable = (GLFBODrawable)offscreenDrawable;
final FBObject.TextureAttachment fboTex = fboDrawable.getTextureBuffer(GL.GL_FRONT);
- fboDrawable.swapBuffers();
fboFlipped.bind(gl);
// gl.glActiveTexture(GL.GL_TEXTURE0 + fboDrawable.getTextureUnit()); // implicit by GLFBODrawableImpl: swapBuffers/contextMadeCurent -> swapFBOImpl