summaryrefslogtreecommitdiffstats
path: root/src/jogl/classes/javax/media/opengl/awt
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2013-09-15 23:27:16 +0200
committerSven Gothel <[email protected]>2013-09-15 23:27:16 +0200
commitc2ce31e11eefcf1b900c0e9b41264f5d5566dc46 (patch)
tree09cc72c0b515bb18062e2bdf14f651981759f6bc /src/jogl/classes/javax/media/opengl/awt
parent5a946df8fd812570826f267d4123b59d79c97cf7 (diff)
Fix AWT printing issues w/ overlapping and/or non-opaque contents ; Change AWTPrintLifecycle's lifecycle
- AWTPrintLifecycle: - Should decorate: PrinterJob.print(..), instead of within Printable.print(..) { .. container.printAll(..); .. } This is due to AWT print implementation, i.e. AWT will issue Printable.print(..) multiple times for 'overlapping' or non-opaque elements! - Move from javax.media.opengl.awt -> com.jogamp.nativewindow.awt - Make _interface_ AWT agnostic, i.e. remove Graphics2D from 'setup(..)' - Add 'int numSamples' to 'setup(..)' to determine the number of samples - AWTTilePrinter: - Use double precision when scaling image-size and clip-rect, then round them to integer values. Otherwise AWT will use the bounding box for the clipping-rectangular. - Clip negative portion of clip-rect, this removes redundant overpaints, as well as increasing the tile count due to the increased clipping-size. - Clip the image-size in the tile-renderer according to the clip-rect. - DEBUG_TILES: Dump tiles to file - Use sub-image of final BuffereImage instead of adding another clipping region. This might increase performance if no clip-rect has been set. TODO: TestTiledPrintingGearsSwingAWT overlapping tests exposes a 'off by one' bug of the first layer's background! Note: The GL content seems to be correct though - maybe it's simply an AWT rounding error ..
Diffstat (limited to 'src/jogl/classes/javax/media/opengl/awt')
-rw-r--r--src/jogl/classes/javax/media/opengl/awt/AWTPrintLifecycle.java162
-rw-r--r--src/jogl/classes/javax/media/opengl/awt/GLCanvas.java33
-rw-r--r--src/jogl/classes/javax/media/opengl/awt/GLJPanel.java47
3 files changed, 25 insertions, 217 deletions
diff --git a/src/jogl/classes/javax/media/opengl/awt/AWTPrintLifecycle.java b/src/jogl/classes/javax/media/opengl/awt/AWTPrintLifecycle.java
deleted file mode 100644
index 1a4c5bac0..000000000
--- a/src/jogl/classes/javax/media/opengl/awt/AWTPrintLifecycle.java
+++ /dev/null
@@ -1,162 +0,0 @@
-/**
- * Copyright 2013 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.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.
- * <a name="impl"><h5>Implementations</h5></a>
- * <p>
- * Implementing {@link GLAutoDrawable} classes based on AWT
- * supporting {@link Component#print(Graphics)} shall implement this interface.
- * </p>
- * <a name="usage"><h5>Usage</h5></a>
- * <p>
- * Users attempting to print an AWT {@link Container} containing {@link AWTPrintLifecycle} elements
- * shall consider decorating the {@link Container#printAll(Graphics)} call with<br>
- * {@link #setupPrint(Graphics2D, double, double) setupPrint(..)} and {@link #releasePrint()}
- * on all {@link AWTPrintLifecycle} elements in the {@link Container}.<br>
- * To minimize this burden, a user can use {@link Context#setupPrint(Container, Graphics2D, double, double) Context.setupPrint(..)}:
- * <pre>
- * Graphics2D g2d;
- * Frame frame;
- * double scaleGLMatXY = 72.0/glDPI;
- * ...
- final AWTPrintLifecycle.Context ctx = AWTPrintLifecycle.Context.setupPrint(frame, g2d, scaleGLMatXY, scaleGLMatXY);
- try {
- AWTEDTExecutor.singleton.invoke(true, new Runnable() {
- public void run() {
- frame.printAll(g2d);
- } });
- } finally {
- ctx.releasePrint();
- }
- *
- * </pre>
- * </p>
- */
-public interface AWTPrintLifecycle {
-
- public static final int DEFAULT_PRINT_TILE_SIZE = 512;
-
-
- /**
- * Shall be called before {@link Component#print(Graphics)}.
- * <p>
- * See <a href="#usage">Usage</a>.
- * </p>
- * @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, double scaleMatX, double scaleMatY);
-
- /**
- * Shall be called after very last {@link Component#print(Graphics)}.
- * <p>
- * See <a href="#usage">Usage</a>.
- * </p>
- */
- void releasePrint();
-
- /**
- * Convenient {@link AWTPrintLifecycle} context simplifying calling {@link AWTPrintLifecycle#setupPrint(Graphics2D, double, double) setupPrint(..)}
- * and {@link AWTPrintLifecycle#releasePrint()} on all {@link AWTPrintLifecycle} elements of a {@link Container}.
- * <p>
- * See <a href="#usage">Usage</a>.
- * </p>
- */
- public static class Context {
- /**
- * <p>
- * See <a href="#usage">Usage</a>.
- * </p>
- *
- * @param c container to be traversed through to perform {@link AWTPrintLifecycle#setupPrint(Graphics2D, double, double) setupPrint(..)} on all {@link AWTPrintLifecycle} elements.
- * @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
- * @return the 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;
- }
-
- /**
- * <p>
- * See <a href="#usage">Usage</a>.
- * </p>
- */
- public void releasePrint() {
- count = AWTMisc.performAction(cont, AWTPrintLifecycle.class, releaseAction);
- }
-
- /**
- * @return count of performed actions of last {@link #setupPrint(Container, Graphics2D, double, double) setupPrint(..)} or {@link #releasePrint()}.
- */
- 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 4e0fdba5d..a519e33bb 100644
--- a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java
+++ b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java
@@ -53,7 +53,6 @@ import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
-import java.awt.RenderingHints;
import java.awt.geom.Rectangle2D;
import java.awt.EventQueue;
@@ -94,6 +93,7 @@ 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;
+import com.jogamp.nativewindow.awt.AWTPrintLifecycle;
import com.jogamp.nativewindow.awt.AWTWindowClosingProtocol;
import com.jogamp.nativewindow.awt.JAWTWindow;
import com.jogamp.opengl.JoglVersion;
@@ -725,13 +725,13 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
}
private volatile boolean printActive = false;
- private boolean printUseAA = false;
+ private int printNumSamples = 0;
private GLAnimatorControl printAnimator = null;
private GLAutoDrawable printGLAD = null;
private AWTTilePainter printAWTTiles = null;
@Override
- public void setupPrint(Graphics2D g2d, double scaleMatX, double scaleMatY) {
+ public void setupPrint(double scaleMatX, double scaleMatY, int numSamples) {
if( !validateGLDrawable() ) {
if(DEBUG) {
System.err.println(getThreadName()+": Info: GLCanvas setupPrint - skipped GL render, drawable not valid yet");
@@ -746,14 +746,9 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
}
printActive = true;
sendReshape = false; // clear reshape flag
- 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 );
- }
+ printNumSamples = AWTTilePainter.getNumSamples(numSamples, getChosenGLCapabilities());
if( DEBUG ) {
- System.err.println("AWT print.setup: canvasSize "+getWidth()+"x"+getWidth()+", scaleMat "+scaleMatX+" x "+scaleMatY+", useAA "+printUseAA+", printAnimator "+printAnimator);
- AWTTilePainter.dumpHintsAndScale(g2d);
+ System.err.println("AWT print.setup: canvasSize "+getWidth()+"x"+getWidth()+", scaleMat "+scaleMatX+" x "+scaleMatY+", numSamples "+numSamples+" -> "+printNumSamples+", printAnimator "+printAnimator);
}
final int componentCount = isOpaque() ? 3 : 4;
final TileRenderer printRenderer = new TileRenderer();
@@ -769,23 +764,15 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
printAnimator.remove(GLCanvas.this);
}
final GLCapabilities caps = (GLCapabilities)getChosenGLCapabilities().cloneMutable();
- final GLProfile glp = caps.getGLProfile();
if( caps.getSampleBuffers() ) {
- // bug / issue w/ swapGLContextAndAllGLEventListener and onscreen MSAA w/ NV/GLX
+ // Bug 830: 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);
- }
+ if( printNumSamples != caps.getNumSamples() ) {
+ caps.setSampleBuffers(0 < printNumSamples);
+ caps.setNumSamples(printNumSamples);
}
final GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile());
printGLAD = factory.createOffscreenAutoDrawable(null, caps, null, DEFAULT_PRINT_TILE_SIZE, DEFAULT_PRINT_TILE_SIZE, null);
@@ -796,7 +783,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
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 AA "+printNumSamples+", "+caps);
System.err.println("AWT print.setup "+printGLAD);
}
}
diff --git a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
index 02f4e54a7..f0c6b7beb 100644
--- a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
+++ b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
@@ -48,7 +48,6 @@ import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsEnvironment;
import java.awt.Rectangle;
-import java.awt.RenderingHints;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;
@@ -90,6 +89,7 @@ import jogamp.opengl.awt.Java2D;
import jogamp.opengl.util.glsl.GLSLTextureRaster;
import com.jogamp.common.util.awt.AWTEDTExecutor;
+import com.jogamp.nativewindow.awt.AWTPrintLifecycle;
import com.jogamp.nativewindow.awt.AWTWindowClosingProtocol;
import com.jogamp.opengl.FBObject;
import com.jogamp.opengl.util.GLPixelBuffer.GLPixelAttributes;
@@ -424,7 +424,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
createAndInitializeBackend();
}
- if (!isInitialized) {
+ if (!isInitialized || printActive) {
return;
}
@@ -498,13 +498,13 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
}
private volatile boolean printActive = false;
- private boolean printUseAA = false;
+ private int printNumSamples = 0;
private GLAnimatorControl printAnimator = null;
private GLAutoDrawable printGLAD = null;
private AWTTilePainter printAWTTiles = null;
@Override
- public void setupPrint(Graphics2D g2d, double scaleMatX, double scaleMatY) {
+ public void setupPrint(double scaleMatX, double scaleMatY, int numSamples) {
if (!isInitialized) {
if(DEBUG) {
System.err.println(getThreadName()+": Info: GLJPanel setupPrint - skipped GL render, drawable not valid yet");
@@ -520,14 +520,9 @@ 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 );
- }
+ printNumSamples = AWTTilePainter.getNumSamples(numSamples, getChosenGLCapabilities());
if( DEBUG ) {
- System.err.println("AWT print.setup: canvasSize "+getWidth()+"x"+getWidth()+", scaleMat "+scaleMatX+" x "+scaleMatY+", useAA "+printUseAA+", printAnimator "+printAnimator);
- AWTTilePainter.dumpHintsAndScale(g2d);
+ System.err.println("AWT print.setup: canvasSize "+getWidth()+"x"+getWidth()+", scaleMat "+scaleMatX+" x "+scaleMatY+", numSamples "+numSamples+" -> "+printNumSamples+", printAnimator "+printAnimator);
}
final int componentCount = isOpaque() ? 3 : 4;
final TileRenderer printRenderer = new TileRenderer();
@@ -546,30 +541,21 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
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, DEFAULT_PRINT_TILE_SIZE, DEFAULT_PRINT_TILE_SIZE, null);
- GLDrawableUtil.swapGLContextAndAllGLEventListener(GLJPanel.this, printGLAD);
- }
+ if( printNumSamples != caps.getNumSamples() ) {
+ caps.setDoubleBuffered(false);
+ caps.setOnscreen(false);
+ caps.setSampleBuffers(0 < printNumSamples);
+ caps.setNumSamples(printNumSamples);
+ final GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile());
+ printGLAD = factory.createOffscreenAutoDrawable(null, caps, null, DEFAULT_PRINT_TILE_SIZE, DEFAULT_PRINT_TILE_SIZE, null);
+ GLDrawableUtil.swapGLContextAndAllGLEventListener(GLJPanel.this, printGLAD);
}
printAWTTiles.setIsGLOriented(printGLAD.isGLOriented());
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 AA "+printNumSamples+", "+caps);
System.err.println("AWT print.setup "+printGLAD);
}
}
@@ -624,9 +610,6 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
printAWTTiles.setupGraphics2DAndClipBounds(g2d, getWidth(), getHeight());
try {
final TileRenderer tileRenderer = printAWTTiles.renderer;
- if( DEBUG ) {
- System.err.println("AWT print.0: "+tileRenderer);
- }
do {
if( printGLAD != GLJPanel.this ) {
tileRenderer.display();