diff options
author | Sven Gothel <[email protected]> | 2014-06-09 03:58:37 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2014-06-09 03:58:37 +0200 |
commit | 4686a652d821efe04045333026be79270bc19bfd (patch) | |
tree | 240ac4df0ae58c7461e7bfdfb3b438917041a3af /src | |
parent | 14ff638b63fc7adaa59f351891f6a38806d7fa5d (diff) |
Bug 741 HiDPI: Add ScalableSurface.getNativeSurfaceScale(..) to compute surface DPI ; Add NEWT Window.getPixelsPerMM(..) to query surface DPI
With HiDPI and surface scale, we need knowledge of the native surface's pixel-scale
matching the monitor's pixel-per-millimeter value.
Preserving the queried native pixel-scale and exposing it via
ScalableSurface.getNativeSurfaceScale(..) to compute surface DPI.
Add NEWT Window.getPixelsPerMM(..) to query surface DPI.
Surface DPI is demonstrated in GraphUI's GPUUISceneGLListener0A .. and TestRulerNEWT01, etc ..
Diffstat (limited to 'src')
21 files changed, 400 insertions, 207 deletions
diff --git a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java index 12db86475..9086d1a78 100644 --- a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java +++ b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java @@ -170,7 +170,8 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing private volatile JAWTWindow jawtWindow; // the JAWTWindow presentation of this AWT Canvas, bound to the 'drawable' lifecycle private volatile GLContextImpl context; // volatile: avoid locking for read-only access private volatile boolean sendReshape = false; // volatile: maybe written by EDT w/o locking - private volatile int[] hasPixelScale = new int[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE }; + private final int[] nativePixelScale = new int[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE }; + private final int[] hasPixelScale = new int[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE }; final int[] reqPixelScale = new int[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE }; // copy of the cstr args, mainly for recreation @@ -692,6 +693,12 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing return result; } + @Override + public int[] getNativeSurfaceScale(final int[] result) { + System.arraycopy(nativePixelScale, 0, result, 0, 2); + return result; + } + private void createJAWTDrawableAndContext() { if ( !Beans.isDesignTime() ) { jawtWindow = (JAWTWindow) NativeWindowFactory.getNativeWindow(this, awtConfig); @@ -702,6 +709,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing drawable = (GLDrawableImpl) GLDrawableFactory.getFactory(capsReqUser.getGLProfile()).createGLDrawable(jawtWindow); createContextImpl(drawable); jawtWindow.getCurrentSurfaceScale(hasPixelScale); + jawtWindow.getNativeSurfaceScale(nativePixelScale); } finally { jawtWindow.unlockSurface(); } @@ -1307,6 +1315,8 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing } hasPixelScale[0] = ScalableSurface.IDENTITY_PIXELSCALE; hasPixelScale[1] = ScalableSurface.IDENTITY_PIXELSCALE; + nativePixelScale[0] = ScalableSurface.IDENTITY_PIXELSCALE; + nativePixelScale[1] = ScalableSurface.IDENTITY_PIXELSCALE; if(null != awtConfig) { final AbstractGraphicsConfiguration aconfig = awtConfig.getNativeGraphicsConfiguration(); diff --git a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java index 223badfb6..21ca0c7ae 100644 --- a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java +++ b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java @@ -247,8 +247,9 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing private boolean handleReshape = false; private boolean sendReshape = true; - private volatile int[] hasPixelScale = new int[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE }; - private volatile int[] reqPixelScale = new int[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE }; + private final int[] nativePixelScale = new int[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE }; + private final int[] hasPixelScale = new int[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE }; + private final int[] reqPixelScale = new int[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE }; // For handling reshape events lazily: reshapeWidth -> panelWidth -> backend.width private int reshapeWidth; @@ -488,6 +489,8 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing } 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"); @@ -568,14 +571,9 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing SurfaceScaleUtils.validateReqPixelScale(reqPixelScale, pixelScale, DEBUG ? getClass().getSimpleName() : null); final Backend b = backend; if ( isInitialized && null != b ) { - final int[] pixelScaleInt; - { - final int ps = JAWTUtil.getPixelScale(getGraphicsConfiguration()); - pixelScaleInt = new int[] { ps, ps }; - } final int hadPixelScaleX = hasPixelScale[0]; final int hadPixelScaleY = hasPixelScale[1]; - SurfaceScaleUtils.computePixelScale(hasPixelScale, hasPixelScale, reqPixelScale, pixelScaleInt, DEBUG ? getClass().getSimpleName() : null); + SurfaceScaleUtils.computePixelScale(hasPixelScale, hasPixelScale, reqPixelScale, nativePixelScale, DEBUG ? getClass().getSimpleName() : null); if( hadPixelScaleX != hasPixelScale[0] || hadPixelScaleY != hasPixelScale[1] ) { updateWrappedSurfaceScale(b.getDrawable()); reshapeImpl(getWidth(), getHeight()); @@ -596,6 +594,12 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing return result; } + @Override + public int[] getNativeSurfaceScale(final int[] result) { + System.arraycopy(nativePixelScale, 0, result, 0, 2); + return result; + } + /** Overridden to track when this component is added to a container. Subclasses which override this method must call super.addNotify() in their addNotify() method in order to @@ -608,12 +612,12 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing awtWindowClosingProtocol.addClosingListener(); // HiDPI support - final int[] pixelScaleInt; { final int ps = JAWTUtil.getPixelScale(getGraphicsConfiguration()); - pixelScaleInt = new int[] { ps, ps }; + nativePixelScale[0] = ps; + nativePixelScale[1] = ps; } - SurfaceScaleUtils.computePixelScale(hasPixelScale, hasPixelScale, reqPixelScale, pixelScaleInt, DEBUG ? getClass().getSimpleName() : null); + SurfaceScaleUtils.computePixelScale(hasPixelScale, hasPixelScale, reqPixelScale, nativePixelScale, DEBUG ? getClass().getSimpleName() : null); if (DEBUG) { System.err.println(getThreadName()+": GLJPanel.addNotify()"); diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java b/src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java index 1cc8fdb01..62710830f 100644 --- a/src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java +++ b/src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java @@ -101,7 +101,8 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface, protected Insets insets; private volatile long offscreenSurfaceLayer; - private volatile int[] hasPixelScale = new int[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE }; + private final int[] nativePixelScale = new int[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE }; + private final int[] hasPixelScale = new int[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE }; protected final int[] reqPixelScale = new int[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE }; private long drawable_old; @@ -266,6 +267,8 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface, insets = new Insets(); hasPixelScale[0] = ScalableSurface.IDENTITY_PIXELSCALE; hasPixelScale[1] = ScalableSurface.IDENTITY_PIXELSCALE; + nativePixelScale[0] = ScalableSurface.IDENTITY_PIXELSCALE; + nativePixelScale[1] = ScalableSurface.IDENTITY_PIXELSCALE; } protected abstract void invalidateNative(); @@ -293,6 +296,12 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface, return result; } + @Override + public final int[] getNativeSurfaceScale(final int[] result) { + System.arraycopy(nativePixelScale, 0, result, 0, 2); + return result; + } + /** * Updates bounds and pixelScale * @return true if bounds or pixelScale has changed, otherwise false @@ -312,6 +321,11 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface, insets.set(contInsets.left, contInsets.right, contInsets.top, contInsets.bottom); } } + { + final int ps = JAWTUtil.getPixelScale(config.getAWTGraphicsConfiguration()); + nativePixelScale[0] = ps; + nativePixelScale[1] = ps; + } return updatePixelScale() || changedBounds; } @@ -321,12 +335,7 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface, * @return true if pixelScale has changed, otherwise false */ protected final boolean updatePixelScale() { - final int[] pixelScaleInt; - { - final int ps = JAWTUtil.getPixelScale(config.getAWTGraphicsConfiguration()); - pixelScaleInt = new int[] { ps, ps }; - } - return SurfaceScaleUtils.computePixelScale(hasPixelScale, hasPixelScale, reqPixelScale, pixelScaleInt, DEBUG ? getClass().getSimpleName() : null); + return SurfaceScaleUtils.computePixelScale(hasPixelScale, hasPixelScale, reqPixelScale, nativePixelScale, DEBUG ? getClass().getSimpleName() : null); } /** @return the JAWT_DrawingSurfaceInfo's (JAWT_Rectangle) bounds, updated with lock */ diff --git a/src/nativewindow/classes/javax/media/nativewindow/ScalableSurface.java b/src/nativewindow/classes/javax/media/nativewindow/ScalableSurface.java index de6ba51d7..ffd5c224c 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/ScalableSurface.java +++ b/src/nativewindow/classes/javax/media/nativewindow/ScalableSurface.java @@ -65,7 +65,7 @@ public interface ScalableSurface { * Returns the requested pixel scale of the associated {@link NativeSurface}. * * @param result int[2] storage for the result - * @return the passed storage containing the requested pixelSize for chaining + * @return the passed storage containing the requested pixelScale for chaining */ int[] getRequestedSurfaceScale(final int[] result); @@ -73,8 +73,25 @@ public interface ScalableSurface { * Returns the current pixel scale of the associated {@link NativeSurface}. * * @param result int[2] storage for the result - * @return the passed storage containing the current pixelSize for chaining + * @return the passed storage containing the current pixelScale for chaining */ public int[] getCurrentSurfaceScale(final int[] result); + + /** + * Returns the native pixel scale of the associated {@link NativeSurface} + * reflecting it's currently bound <i>monitor surface resolution in pixels</i>. + * <p> + * The native pixel scale maybe used to determine the proper <i>dpi</i> + * value of this {@link NativeSurface}: + * <pre> + * surfacePpMM = monitorPpMM * currentSurfaceScale / nativeSurfaceScale, + * with PpMM == pixel per millimeter + * </pre> + * </p> + * + * @param result int[2] storage for the result + * @return the passed storage containing the native pixelScale for chaining + */ + public int[] getNativeSurfaceScale(final int[] result); } diff --git a/src/nativewindow/classes/javax/media/nativewindow/util/Dimension.java b/src/nativewindow/classes/javax/media/nativewindow/util/Dimension.java index 24ccc836a..5c9dc279d 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/util/Dimension.java +++ b/src/nativewindow/classes/javax/media/nativewindow/util/Dimension.java @@ -37,7 +37,11 @@ public class Dimension implements Cloneable, DimensionImmutable { this(0, 0); } - public Dimension(int width, int height) { + public Dimension(final int[] size) { + this(size[0], size[1]); + } + + public Dimension(final int width, final int height) { if(width<0 || height<0) { throw new IllegalArgumentException("width and height must be within: ["+0+".."+Integer.MAX_VALUE+"]"); } diff --git a/src/nativewindow/classes/jogamp/nativewindow/SurfaceScaleUtils.java b/src/nativewindow/classes/jogamp/nativewindow/SurfaceScaleUtils.java index 22e67ecff..3aea58852 100644 --- a/src/nativewindow/classes/jogamp/nativewindow/SurfaceScaleUtils.java +++ b/src/nativewindow/classes/jogamp/nativewindow/SurfaceScaleUtils.java @@ -58,37 +58,34 @@ public class SurfaceScaleUtils { * @param result int[2] storage for result, maybe same as <code>prePixelScale</code> for in-place * @param prePixelScale previous pixelScale * @param reqPixelScale requested pixelScale, validated via {@link #validateReqPixelScale(int[], int, String)}. - * @param surfPixelScaleRaw raw surface pixelScale + * @param newPixelScaleRaw new raw surface pixelScale * @param DEBUG_PREFIX if set, dumps debug info on stderr using this prefix * @return true if pixelScale has changed, otherwise false */ - public static boolean computePixelScale(int[] result, final int[] prePixelScale, final int[] reqPixelScale, final int[] surfPixelScaleRaw, final String DEBUG_PREFIX) { - final int surfPixelScaleSafeX = 0 < surfPixelScaleRaw[0] ? surfPixelScaleRaw[0] : ScalableSurface.IDENTITY_PIXELSCALE; - final int surfPixelScaleSafeY = 0 < surfPixelScaleRaw[1] ? surfPixelScaleRaw[1] : ScalableSurface.IDENTITY_PIXELSCALE; + public static boolean computePixelScale(int[] result, final int[] prePixelScale, final int[] reqPixelScale, final int[] newPixelScaleRaw, final String DEBUG_PREFIX) { + final int newPixelScaleSafeX = 0 < newPixelScaleRaw[0] ? newPixelScaleRaw[0] : ScalableSurface.IDENTITY_PIXELSCALE; + final int newPixelScaleSafeY = 0 < newPixelScaleRaw[1] ? newPixelScaleRaw[1] : ScalableSurface.IDENTITY_PIXELSCALE; final boolean useHiDPI = ScalableSurface.IDENTITY_PIXELSCALE != reqPixelScale[0] || ScalableSurface.IDENTITY_PIXELSCALE != reqPixelScale[1]; final int prePixelScaleX = prePixelScale[0]; final int prePixelScaleY = prePixelScale[1]; if( useHiDPI ) { - result[0] = surfPixelScaleSafeX; - result[1] = surfPixelScaleSafeY; + result[0] = newPixelScaleSafeX; + result[1] = newPixelScaleSafeY; } else { result[0] = ScalableSurface.IDENTITY_PIXELSCALE; result[1] = ScalableSurface.IDENTITY_PIXELSCALE; } - if( result[0] != prePixelScaleX || result[1] != prePixelScaleY ) { - if( null != DEBUG_PREFIX ) { - System.err.println(DEBUG_PREFIX+".computePixelScale: useHiDPI "+useHiDPI+", ["+prePixelScaleX+"x"+prePixelScaleY+" (pre), "+ - reqPixelScale[0]+"x"+reqPixelScale[1]+" (req)] -> "+ - surfPixelScaleRaw[0]+"x"+surfPixelScaleRaw[1]+" (raw) -> "+ - surfPixelScaleSafeX+"x"+surfPixelScaleSafeY+" (safe) -> "+ - result[0]+"x"+result[1]+" (use)"); - } - return true; - } else { - return false; + final boolean changed = result[0] != prePixelScaleX || result[1] != prePixelScaleY; + if( null != DEBUG_PREFIX ) { + System.err.println(DEBUG_PREFIX+".computePixelScale: useHiDPI "+useHiDPI+", ["+prePixelScaleX+"x"+prePixelScaleY+" (pre), "+ + reqPixelScale[0]+"x"+reqPixelScale[1]+" (req)] -> "+ + newPixelScaleRaw[0]+"x"+newPixelScaleRaw[1]+" (raw) -> "+ + newPixelScaleSafeX+"x"+newPixelScaleSafeY+" (safe) -> "+ + result[0]+"x"+result[1]+" (use), changed "+changed); } + return changed; } /** diff --git a/src/nativewindow/classes/jogamp/nativewindow/WrappedSurface.java b/src/nativewindow/classes/jogamp/nativewindow/WrappedSurface.java index 8f9379130..752057a49 100644 --- a/src/nativewindow/classes/jogamp/nativewindow/WrappedSurface.java +++ b/src/nativewindow/classes/jogamp/nativewindow/WrappedSurface.java @@ -164,4 +164,10 @@ public class WrappedSurface extends ProxySurfaceImpl implements ScalableSurface return result; } + @Override + public final int[] getNativeSurfaceScale(final int[] result) { + System.arraycopy(hasPixelScale, 0, result, 0, 2); + return result; + } + }
\ No newline at end of file diff --git a/src/newt/classes/com/jogamp/newt/MonitorDevice.java b/src/newt/classes/com/jogamp/newt/MonitorDevice.java index 8e5d305dd..a65675204 100644 --- a/src/newt/classes/com/jogamp/newt/MonitorDevice.java +++ b/src/newt/classes/com/jogamp/newt/MonitorDevice.java @@ -34,6 +34,7 @@ import javax.media.nativewindow.util.DimensionImmutable; import javax.media.nativewindow.util.Rectangle; import javax.media.nativewindow.util.RectangleImmutable; import javax.media.nativewindow.util.SurfaceSize; + import com.jogamp.common.util.ArrayHashSet; /** @@ -124,29 +125,34 @@ public abstract class MonitorDevice { } /** - * Stores the <i>pixels per millimeter</i> value according to <i>current</i> {@link MonitorMode} - * {@link SurfaceSize#getResolution() SurfaceSize's resolution} in the given storage <code>ppmmStore</code>. + * Returns the <i>pixels per millimeter</i> value according to the <i>current</i> {@link MonitorMode mode}'s + * {@link SurfaceSize#getResolution() surface resolution}. * <p> * To convert the result to <i>dpi</i>, i.e. dots-per-inch, multiply both components with <code>25.4f</code>. * </p> + * @param ppmmStore float[2] storage for the ppmm result + * @return the passed storage containing the ppmm for chaining */ - public final void getPixelsPerMM(final float[] ppmmStore) { - final MonitorMode mode = getCurrentMode(); - getPixelsPerMM(mode, ppmmStore); + public final float[] getPixelsPerMM(final float[] ppmmStore) { + return getPixelsPerMM(getCurrentMode(), ppmmStore); } /** - * Stores the <i>pixels per millimeter</i> value according to the given {@link MonitorMode} - * {@link SurfaceSize#getResolution() SurfaceSize's resolution} in the given storage <code>ppmmStore</code>. + * Returns the <i>pixels per millimeter</i> value according to the given {@link MonitorMode mode}'s + * {@link SurfaceSize#getResolution() surface resolution}. * <p> * To convert the result to <i>dpi</i>, i.e. dots-per-inch, multiply both components with <code>25.4f</code>. * </p> + * @param mode + * @param ppmmStore float[2] storage for the ppmm result + * @return the passed storage containing the ppmm for chaining */ - public final void getPixelsPerMM(final MonitorMode mode, final float[] ppmmStore) { + public final float[] getPixelsPerMM(final MonitorMode mode, final float[] ppmmStore) { final DimensionImmutable sdim = getSizeMM(); final DimensionImmutable spix = mode.getSurfaceSize().getResolution(); ppmmStore[0] = (float)spix.getWidth() / (float)sdim.getWidth(); ppmmStore[1] = (float)spix.getHeight() / (float)sdim.getHeight(); + return ppmmStore; } /** diff --git a/src/newt/classes/com/jogamp/newt/Window.java b/src/newt/classes/com/jogamp/newt/Window.java index 08236ae67..600ecee52 100644 --- a/src/newt/classes/com/jogamp/newt/Window.java +++ b/src/newt/classes/com/jogamp/newt/Window.java @@ -49,6 +49,7 @@ import javax.media.nativewindow.ScalableSurface; import javax.media.nativewindow.WindowClosingProtocol; import javax.media.nativewindow.util.Rectangle; import javax.media.nativewindow.util.RectangleImmutable; +import javax.media.nativewindow.util.SurfaceSize; /** * Specifying NEWT's Window functionality: @@ -254,6 +255,26 @@ public interface Window extends NativeWindow, WindowClosingProtocol, ScalableSur Rectangle getBounds(); /** + * Returns the <i>pixels per millimeter</i> of this window's {@link NativeSurface} + * according to the {@link #getMainMonitor() main monitor}'s <i>current</i> {@link MonitorMode mode}'s + * {@link SurfaceSize#getResolution() surface resolution}. + * <p> + * Method takes the {@link #getCurrentSurfaceScale(int[]) current surface-scale} and {@link #getNativeSurfaceScale(int[]) native surface-scale} + * into account, i.e.: + * <pre> + * surfacePpMM = monitorPpMM * currentSurfaceScale / nativeSurfaceScale, + * with PpMM == pixel per millimeter + * </pre> + * </p> + * <p> + * To convert the result to <i>dpi</i>, i.e. dots-per-inch, multiply both components with <code>25.4f</code>. + * </p> + * @param ppmmStore float[2] storage for the ppmm result + * @return the passed storage containing the ppmm for chaining + */ + float[] getPixelsPerMM(final float[] ppmmStore); + + /** * Sets the size of the window's client area in window units, excluding decorations. * * <p> diff --git a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java index 2991bb98a..cdc4f1217 100644 --- a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java +++ b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java @@ -404,6 +404,16 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind } @Override + public final int[] getNativeSurfaceScale(final int[] result) { + return window.getNativeSurfaceScale(result); + } + + @Override + public final float[] getPixelsPerMM(final float[] ppmmStore) { + return window.getPixelsPerMM(ppmmStore); + } + + @Override public final void setPosition(int x, int y) { window.setPosition(x, y); } diff --git a/src/newt/classes/jogamp/newt/WindowImpl.java b/src/newt/classes/jogamp/newt/WindowImpl.java index 0501f6ad6..61fa7af6b 100644 --- a/src/newt/classes/jogamp/newt/WindowImpl.java +++ b/src/newt/classes/jogamp/newt/WindowImpl.java @@ -152,8 +152,9 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer private volatile boolean hasFocus = false; private volatile int pixWidth = 128, pixHeight = 128; // client-area size w/o insets in pixel units, default: may be overwritten by user private volatile int winWidth = 128, winHeight = 128; // client-area size w/o insets in window units, default: may be overwritten by user - protected int[] hasPixelScale = new int[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE }; - protected int[] reqPixelScale = new int[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE }; + protected final int[] nativePixelScale = new int[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE }; + protected final int[] hasPixelScale = new int[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE }; + protected final int[] reqPixelScale = new int[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE }; private volatile int x = 64, y = 64; // client-area pos w/o insets in window units private volatile Insets insets = new Insets(); // insets of decoration (if top-level && decorated) @@ -1092,7 +1093,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer setSize(width - getInsets().getTotalWidth(), height - getInsets().getTotalHeight()); } - private class DestroyAction implements Runnable { + private final Runnable destroyAction = new Runnable() { @Override public final void run() { boolean animatorPaused = false; @@ -1164,6 +1165,10 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer fullscreenUseMainMonitor = true; hasFocus = false; parentWindowHandle = 0; + hasPixelScale[0] = ScalableSurface.IDENTITY_PIXELSCALE; + hasPixelScale[1] = ScalableSurface.IDENTITY_PIXELSCALE; + nativePixelScale[0] = ScalableSurface.IDENTITY_PIXELSCALE; + nativePixelScale[1] = ScalableSurface.IDENTITY_PIXELSCALE; _lock.unlock(); } @@ -1187,9 +1192,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer windowListeners = null; parentWindow = null; */ - } - } - private final DestroyAction destroyAction = new DestroyAction(); + } }; @Override public void destroy() { @@ -1567,7 +1570,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer } } - private class ReparentActionRecreate implements Runnable { + private final Runnable reparentActionRecreate = new Runnable() { @Override public final void run() { final RecursiveLock _lock = windowLock; @@ -1581,9 +1584,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer } finally { _lock.unlock(); } - } - } - private final ReparentActionRecreate reparentActionRecreate = new ReparentActionRecreate(); + } }; @Override public final ReparentOperation reparentWindow(NativeWindow newParent, int x, int y, int hints) { @@ -1958,6 +1959,20 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer return result; } + @Override + public final int[] getNativeSurfaceScale(final int[] result) { + System.arraycopy(nativePixelScale, 0, result, 0, 2); + return result; + } + + @Override + public final float[] getPixelsPerMM(final float[] ppmmStore) { + getMainMonitor().getPixelsPerMM(ppmmStore); + ppmmStore[0] *= (float)hasPixelScale[0] / (float)nativePixelScale[0]; + ppmmStore[1] *= (float)hasPixelScale[1] / (float)nativePixelScale[1]; + return ppmmStore; + } + protected final boolean autoPosition() { return autoPosition; } /** Sets the position fields {@link #x} and {@link #y} in window units to the given values and {@link #autoPosition} to false. */ diff --git a/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java index 498556630..b44c2a3cc 100644 --- a/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java +++ b/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java @@ -67,14 +67,18 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl public WindowDriver() { } - private boolean updatePixelScale(final boolean sendEvent, final boolean defer, final float pixelScaleRaw) { - final int[] pixelScaleInt; + private boolean updatePixelScale(final boolean sendEvent, final boolean defer, final float newPixelScaleRaw, final float nativePixelScaleRaw) { + final int[] newPixelScale = new int[2]; { - final int ps = FloatUtil.isZero(pixelScaleRaw, FloatUtil.EPSILON) ? 1 : (int) pixelScaleRaw; - pixelScaleInt = new int[] { ps, ps }; + final int _newPixelScale = FloatUtil.isZero(newPixelScaleRaw, FloatUtil.EPSILON) ? ScalableSurface.IDENTITY_PIXELSCALE : (int) newPixelScaleRaw; + newPixelScale[0]= _newPixelScale; + newPixelScale[1]= _newPixelScale; + final int _nativePixelScale = FloatUtil.isZero(nativePixelScaleRaw, FloatUtil.EPSILON) ? ScalableSurface.IDENTITY_PIXELSCALE : (int) nativePixelScaleRaw; + nativePixelScale[0]= _nativePixelScale; + nativePixelScale[1]= _nativePixelScale; } - if( SurfaceScaleUtils.computePixelScale(hasPixelScale, hasPixelScale, reqPixelScale, pixelScaleInt, DEBUG_IMPLEMENTATION ? getClass().getName() : null) ) { + if( SurfaceScaleUtils.computePixelScale(hasPixelScale, hasPixelScale, reqPixelScale, newPixelScale, DEBUG_IMPLEMENTATION ? getClass().getName() : null) ) { if( sendEvent ) { super.sizeChanged(defer, getWidth(), getHeight(), true); } else { @@ -87,34 +91,34 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl } private boolean updatePixelScaleByScreenIdx(final boolean sendEvent) { - final float newPixelScaleRaw = (float) OSXUtil.GetPixelScale(getScreen().getIndex()); + final float nativePixelScaleRaw = (float) OSXUtil.GetPixelScale(getScreen().getIndex()); if( DEBUG_IMPLEMENTATION ) { - System.err.println("WindowDriver.updatePixelScale.1: "+hasPixelScale[0]+" -> "+newPixelScaleRaw); + System.err.println("WindowDriver.updatePixelScale.1: "+hasPixelScale[0]+", "+nativePixelScaleRaw+" (native)"); } - return updatePixelScale(sendEvent, true /* defer */, newPixelScaleRaw); + return updatePixelScale(sendEvent, true /* defer */, nativePixelScaleRaw, nativePixelScaleRaw); } private boolean updatePixelScaleByWindowHandle(final boolean sendEvent) { final long handle = getWindowHandle(); if( 0 != handle ) { - final float newPixelScaleRaw = (float)OSXUtil.GetPixelScale(handle); + final float nativePixelScaleRaw = (float)OSXUtil.GetPixelScale(handle); if( DEBUG_IMPLEMENTATION ) { - System.err.println("WindowDriver.updatePixelScale.2: "+hasPixelScale[0]+" -> "+newPixelScaleRaw); + System.err.println("WindowDriver.updatePixelScale.2: "+hasPixelScale[0]+", "+nativePixelScaleRaw+" (native)"); } - return updatePixelScale(sendEvent, true /* defer */, newPixelScaleRaw); + return updatePixelScale(sendEvent, true /* defer */, nativePixelScaleRaw, nativePixelScaleRaw); } else { return false; } } /** Called from native code */ - protected void updatePixelScale(final boolean defer, final float newPixelScaleRaw) { + protected void updatePixelScale(final boolean defer, final float newPixelScaleRaw, final float nativePixelScaleRaw) { final long handle = getWindowHandle(); if( DEBUG_IMPLEMENTATION ) { - System.err.println("WindowDriver.updatePixelScale.3: "+hasPixelScale[0]+" (has) -> "+newPixelScaleRaw+" (raw), drop "+(0==handle)); + System.err.println("WindowDriver.updatePixelScale.3: "+hasPixelScale[0]+" (has) -> "+newPixelScaleRaw+" (raw), "+nativePixelScaleRaw+" (native), drop "+(0==handle)); } if( 0 != handle ) { - updatePixelScale(true /* sendEvent*/, defer, newPixelScaleRaw); + updatePixelScale(true /* sendEvent*/, defer, newPixelScaleRaw, nativePixelScaleRaw); } } @@ -146,11 +150,12 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl final ScalableSurface sSurf = (ScalableSurface)pWin; sSurf.setSurfaceScale(reqPixelScale); final int[] pPixelScale = sSurf.getCurrentSurfaceScale(new int[2]); - updatePixelScale(true /* sendEvent */, true /* defer */, pPixelScale[0]); // HiDPI: uniformPixelScale + sSurf.getNativeSurfaceScale(nativePixelScale); + updatePixelScale(true /* sendEvent */, true /* defer */, pPixelScale[0], nativePixelScale[0]); // HiDPI: uniformPixelScale } else { // just notify updated pixelScale if offscreen SurfaceScaleUtils.replaceAutoMaxWithPlatformMax(reqPixelScale); - updatePixelScale(true /* sendEvent */, true /* defer */, reqPixelScale[0]); // HiDPI: uniformPixelScale + updatePixelScale(true /* sendEvent */, true /* defer */, reqPixelScale[0], nativePixelScale[0]); // HiDPI: uniformPixelScale } } else { // set pixelScale in native code, will issue an update PixelScale diff --git a/src/newt/native/NewtMacWindow.m b/src/newt/native/NewtMacWindow.m index fe761833d..5a1963155 100644 --- a/src/newt/native/NewtMacWindow.m +++ b/src/newt/native/NewtMacWindow.m @@ -780,9 +780,9 @@ static jmethodID windowRepaintID = NULL; // HiDPI scaling BOOL useHiDPI = [self wantsBestResolutionOpenGLSurface]; - CGFloat pixelScaleRaw = [[self window] backingScaleFactor]; - CGFloat pixelScaleUse = useHiDPI ? pixelScaleRaw : 1.0; - DBG_PRINT("viewDidChangeBackingProperties: PixelScale: HiDPI %d, raw %f -> use %f\n", useHiDPI, (float)pixelScaleRaw, (float)pixelScaleUse); + CGFloat pixelScaleNative = [[self window] backingScaleFactor]; + CGFloat pixelScaleUse = useHiDPI ? pixelScaleNative : 1.0; + DBG_PRINT("viewDidChangeBackingProperties: PixelScale: HiDPI %d, native %f -> use %f\n", useHiDPI, (float)pixelScaleNative, (float)pixelScaleUse); [[self layer] setContentsScale: pixelScaleUse]; if (javaWindowObject == NULL) { @@ -796,7 +796,7 @@ static jmethodID windowRepaintID = NULL; return; } - (*env)->CallVoidMethod(env, javaWindowObject, updatePixelScaleID, JNI_TRUE, (jfloat)pixelScaleUse); // defer + (*env)->CallVoidMethod(env, javaWindowObject, updatePixelScaleID, JNI_TRUE, (jfloat)pixelScaleUse, (jfloat)pixelScaleNative); // defer // detaching thread not required - daemon // NewtCommon_ReleaseJNIEnv(shallBeDetached); @@ -812,7 +812,7 @@ static jmethodID windowRepaintID = NULL; enqueueMouseEventID = (*env)->GetMethodID(env, clazz, "enqueueMouseEvent", "(ZSIIISF)V"); enqueueKeyEventID = (*env)->GetMethodID(env, clazz, "enqueueKeyEvent", "(ZSISCC)V"); sizeChangedID = (*env)->GetMethodID(env, clazz, "sizeChanged", "(ZIIZ)V"); - updatePixelScaleID = (*env)->GetMethodID(env, clazz, "updatePixelScale", "(ZF)V"); + updatePixelScaleID = (*env)->GetMethodID(env, clazz, "updatePixelScale", "(ZFF)V"); visibleChangedID = (*env)->GetMethodID(env, clazz, "visibleChanged", "(ZZ)V"); insetsChangedID = (*env)->GetMethodID(env, clazz, "insetsChanged", "(ZIIII)V"); positionChangedID = (*env)->GetMethodID(env, clazz, "screenPositionChanged", "(ZII)V"); 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 ad95b3502..2e0be5b79 100644 --- a/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT00.java +++ b/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT00.java @@ -53,7 +53,6 @@ import com.jogamp.graph.curve.opengl.RenderState; import com.jogamp.graph.font.Font; import com.jogamp.graph.font.FontFactory; import com.jogamp.graph.geom.SVertex; -import com.jogamp.newt.MonitorDevice; import com.jogamp.newt.Window; import com.jogamp.newt.opengl.GLWindow; import com.jogamp.opengl.test.junit.util.MiscUtils; @@ -312,9 +311,7 @@ public class TestTextRendererNEWT00 extends UITestCase { t0 = Platform.currentTimeMillis(); final Window win = (Window)drawable.getUpstreamWidget(); - final MonitorDevice monitor = win.getMainMonitor(); - final float[] pixelsPerMM = new float[2]; - monitor.getPixelsPerMM(pixelsPerMM); + final float[] pixelsPerMM = win.getPixelsPerMM(new float[2]); final float[] dotsPerInch = new float[] { pixelsPerMM[0]*25.4f, pixelsPerMM[1]*25.4f }; dpiH = dotsPerInch[1]; System.err.println(getFontInfo()); diff --git a/src/test/com/jogamp/opengl/test/junit/graph/TextRendererGLELBase.java b/src/test/com/jogamp/opengl/test/junit/graph/TextRendererGLELBase.java index f948b9beb..1c4a20bea 100644 --- a/src/test/com/jogamp/opengl/test/junit/graph/TextRendererGLELBase.java +++ b/src/test/com/jogamp/opengl/test/junit/graph/TextRendererGLELBase.java @@ -145,8 +145,7 @@ public abstract class TextRendererGLELBase implements GLEventListener { final Object upObj = drawable.getUpstreamWidget(); if( upObj instanceof Window ) { - final float[] pixelsPerMM = new float[2]; - ((Window)upObj).getMainMonitor().getPixelsPerMM(pixelsPerMM); + final float[] pixelsPerMM = ((Window)upObj).getPixelsPerMM(new float[2]); dpiH = pixelsPerMM[1]*25.4f; } } diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUTextRendererListenerBase01.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUTextRendererListenerBase01.java index 89aa4d0ee..76bcfd094 100644 --- a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUTextRendererListenerBase01.java +++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUTextRendererListenerBase01.java @@ -166,7 +166,7 @@ public abstract class GPUTextRendererListenerBase01 extends GPURendererListenerB final Object upObj = drawable.getUpstreamWidget(); if( upObj instanceof Window ) { final float[] pixelsPerMM = new float[2]; - ((Window)upObj).getMainMonitor().getPixelsPerMM(pixelsPerMM); + ((Window)upObj).getPixelsPerMM(pixelsPerMM); dpiH = pixelsPerMM[1]*25.4f; } fontNameBox = font.getMetricBounds(fontName, font.getPixelSize(fontSizeFName, dpiH)); diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneGLListener0A.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneGLListener0A.java index 6a1f60de7..fbb29d6ea 100644 --- a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneGLListener0A.java +++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneGLListener0A.java @@ -8,6 +8,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import javax.media.nativewindow.util.Dimension; import javax.media.opengl.GL; import javax.media.opengl.GL2ES2; import javax.media.opengl.GLAnimatorControl; @@ -86,7 +87,7 @@ public class GPUUISceneGLListener0A implements GLEventListener { * @see #GPUUISceneGLListener0A(float) * @see #GPUUISceneGLListener0A(float, boolean, boolean) */ - public static final float DefaultNoAADPIThreshold = 180f; + public static final float DefaultNoAADPIThreshold = 200f; private int currentText = 0; @@ -624,12 +625,16 @@ public class GPUUISceneGLListener0A implements GLEventListener { public void init(GLAutoDrawable drawable) { final Object upObj = drawable.getUpstreamWidget(); if( upObj instanceof Window ) { - final float[] pixelsPerMM = new float[2]; - final MonitorDevice mm = ((Window)upObj).getMainMonitor(); - mm.getPixelsPerMM(pixelsPerMM); - dpiH = pixelsPerMM[1]*25.4f; + final Window upWin = (Window)upObj; + final MonitorDevice mm = upWin.getMainMonitor(); + final float[] monitorPixelsPerMM = mm.getPixelsPerMM(new float[2]); + final float monitorDpiH = monitorPixelsPerMM[1]*25.4f; + final float[] surfacePixelsPerMM = upWin.getPixelsPerMM(new float[2]); + dpiH = surfacePixelsPerMM[1]*25.4f; System.err.println("Monitor detected: "+mm); - System.err.println("Using monitor's DPI of "+(pixelsPerMM[0]*25.4f)+" x "+dpiH+" -> "+dpiH); + System.err.println("Monitor dpi: "+monitorDpiH); + System.err.println("Surface scale: native "+new Dimension(upWin.getNativeSurfaceScale(new int[2]))+", current "+new Dimension(upWin.getCurrentSurfaceScale(new int[2]))); + System.err.println("Surface dpi: "+dpiH); } else { System.err.println("Using default DPI of "+dpiH); } @@ -818,7 +823,6 @@ public class GPUUISceneGLListener0A implements GLEventListener { final float dz = 0f; final float dyTop = dh * relTop; - final float dxMiddle = dw * relMiddle; final float dxLeft = dw * relLeft; final float dxRight = dw; diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneNewtCanvasAWTDemo.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneNewtCanvasAWTDemo.java index a80b70830..011b20c35 100644 --- a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneNewtCanvasAWTDemo.java +++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneNewtCanvasAWTDemo.java @@ -4,6 +4,7 @@ import java.awt.Component; import java.awt.Frame; import java.lang.reflect.InvocationTargetException; +import javax.media.nativewindow.ScalableSurface; import javax.media.nativewindow.util.Dimension; import javax.media.nativewindow.util.DimensionImmutable; import javax.media.opengl.GLCapabilities; @@ -29,6 +30,8 @@ public class GPUUISceneNewtCanvasAWTDemo { static boolean GraphMSAAMode = false; static float GraphAutoMode = GPUUISceneGLListener0A.DefaultNoAADPIThreshold; + static int[] reqSurfacePixelScale = new int[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE }; + static void setComponentSize(final Component comp, final DimensionImmutable new_sz) { try { javax.swing.SwingUtilities.invokeAndWait(new Runnable() { @@ -80,6 +83,11 @@ public class GPUUISceneNewtCanvasAWTDemo { } else if(args[i].equals("-y")) { i++; y = MiscUtils.atoi(args[i], y); + } else if(args[i].equals("-pixelScale")) { + i++; + final int pS = MiscUtils.atoi(args[i], reqSurfacePixelScale[0]); + reqSurfacePixelScale[0] = pS; + reqSurfacePixelScale[1] = pS; } } } @@ -114,6 +122,8 @@ public class GPUUISceneNewtCanvasAWTDemo { window.setPosition(x, y); window.setSize(width, height); window.setTitle("GraphUI Newt Demo: graph["+Region.getRenderModeString(rmode)+"], msaa "+SceneMSAASamples); + window.setSurfaceScale(reqSurfacePixelScale); + final int[] valReqSurfacePixelScale = window.getRequestedSurfaceScale(new int[2]); GPUUISceneGLListener0A sceneGLListener = 0 < GraphAutoMode ? new GPUUISceneGLListener0A(GraphAutoMode, DEBUG, TRACE) : new GPUUISceneGLListener0A(rmode, DEBUG, TRACE); @@ -142,6 +152,10 @@ public class GPUUISceneNewtCanvasAWTDemo { frame.setVisible(true); } }); + final int[] hasSurfacePixelScale1 = window.getCurrentSurfaceScale(new int[2]); + System.err.println("HiDPI PixelScale: "+reqSurfacePixelScale[0]+"x"+reqSurfacePixelScale[1]+" (req) -> "+ + valReqSurfacePixelScale[0]+"x"+valReqSurfacePixelScale[1]+" (val) -> "+ + hasSurfacePixelScale1[0]+"x"+hasSurfacePixelScale1[1]+" (has)"); animator.start(); } } 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 3e78360f5..f2fdcb351 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 @@ -122,7 +122,10 @@ public class TestGearsES2NEWT extends UITestCase { private void setTitle(final Window win, final GLCapabilitiesImmutable caps) { final String capsA = caps.isBackgroundOpaque() ? "opaque" : "transl"; - win.setTitle("GLWindow["+capsA+"], swapI "+swapInterval+", win: "+win.getBounds()+", pix: "+win.getSurfaceWidth()+"x"+win.getSurfaceHeight()); + final float[] sDPI = win.getPixelsPerMM(new float[2]); + sDPI[0] *= 25.4f; + sDPI[1] *= 25.4f; + win.setTitle("GLWindow["+capsA+"], swapI "+swapInterval+", win: "+win.getBounds()+", pix: "+win.getSurfaceWidth()+"x"+win.getSurfaceHeight()+", sDPI "+sDPI[0]+" x "+sDPI[1]); } protected void runTestGL(final GLCapabilitiesImmutable caps, boolean undecorated) throws InterruptedException { System.err.println("requested: vsync "+swapInterval+", "+caps); @@ -141,7 +144,6 @@ public class TestGearsES2NEWT extends UITestCase { glWindow.setFullscreen(fullscreen); glWindow.setPointerVisible(mouseVisible); glWindow.confinePointer(mouseConfined); - setTitle(glWindow, caps); final GearsES2 demo = new GearsES2(swapInterval); demo.setPMVUseBackingArray(pmvUseBackingArray); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NewtCanvasAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NewtCanvasAWT.java index 694efeaf4..08c81c59e 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NewtCanvasAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NewtCanvasAWT.java @@ -181,7 +181,10 @@ public class TestGearsES2NewtCanvasAWT extends UITestCase { final java.awt.Rectangle b = glc.getBounds(); frame.setTitle("NewtCanvasAWT["+capsA+"], swapI "+swapInterval+", win: ["+b.x+"/"+b.y+" "+b.width+"x"+b.height+"], pix: "+glc.getNativeWindow().getSurfaceWidth()+"x"+glc.getNativeWindow().getSurfaceHeight()); } - win.setTitle("GLWindow["+capsA+"], swapI "+swapInterval+", win: "+win.getBounds()+", pix: "+win.getSurfaceWidth()+"x"+win.getSurfaceHeight()); + final float[] sDPI = win.getPixelsPerMM(new float[2]); + sDPI[0] *= 25.4f; + sDPI[1] *= 25.4f; + win.setTitle("GLWindow["+capsA+"], swapI "+swapInterval+", win: "+win.getBounds()+", pix: "+win.getSurfaceWidth()+"x"+win.getSurfaceHeight()+", sDPI "+sDPI[0]+" x "+sDPI[1]); } // public enum ResizeBy { GLWindow, Component, Frame }; diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestRulerNEWT01.java b/src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestRulerNEWT01.java index 0384765bf..b9d77ac0c 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestRulerNEWT01.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestRulerNEWT01.java @@ -28,7 +28,10 @@ package com.jogamp.opengl.test.junit.jogl.glsl; import com.jogamp.common.nio.Buffers; -import com.jogamp.newt.MonitorDevice; +import com.jogamp.newt.Window; +import com.jogamp.newt.event.KeyAdapter; +import com.jogamp.newt.event.KeyEvent; +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; @@ -36,16 +39,18 @@ import com.jogamp.opengl.util.glsl.ShaderProgram; import com.jogamp.opengl.util.glsl.ShaderState; 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 java.lang.reflect.InvocationTargetException; import java.nio.FloatBuffer; +import javax.media.nativewindow.ScalableSurface; import javax.media.opengl.GL; import javax.media.opengl.GL2ES2; +import javax.media.opengl.GLAutoDrawable; import javax.media.opengl.GLCapabilities; -import javax.media.opengl.GLDrawable; +import javax.media.opengl.GLEventListener; import javax.media.opengl.GLProfile; import javax.media.opengl.GLUniformData; @@ -56,120 +61,178 @@ import org.junit.runners.MethodSorters; @FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestRulerNEWT01 extends UITestCase { - static long durationPerTest = 10; // ms + static long durationPerTest = 500; // ms + static int[] reqSurfacePixelScale = new int[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE }; + static boolean manualTest = false; - @Test - public void test01() throws InterruptedException { - long t0 = System.nanoTime(); - GLProfile.initSingleton(); - long t1 = System.nanoTime(); - // preset .. - final NEWTGLContext.WindowContext winctx = NEWTGLContext.createOnscreenWindow( - new GLCapabilities(GLProfile.getGL2ES2()), 640, 480, true); - final GLDrawable drawable = winctx.context.getGLDrawable(); - final GL2ES2 gl = winctx.context.getGL().getGL2ES2(); - System.err.println(winctx.context); - - Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); - // test code .. - final ShaderState st = new ShaderState(); - - final ShaderCode vp0 = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, RedSquareES2.class, "shader", - "shader/bin", "default", true); - final ShaderCode fp0 = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, RedSquareES2.class, "shader", - "shader/bin", "ruler", true); - vp0.defaultShaderCustomization(gl, true, true); - fp0.defaultShaderCustomization(gl, true, true); - - 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, 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 GLUniformData rulerColor= new GLUniformData("gcu_RulerColor", 3, Buffers.newDirectFloatBuffer(3)); - final FloatBuffer rulerColorV = (FloatBuffer) rulerColor.getBuffer(); - rulerColorV.put(0, 0.5f); - rulerColorV.put(1, 0.5f); - rulerColorV.put(2, 0.5f); - st.ownUniform(rulerColor); - st.uniform(gl, rulerColor); - Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); - - Assert.assertNotNull(winctx); - Assert.assertNotNull(winctx.window); - Assert.assertNotNull(winctx.window.getScreen()); - final float[] ppmmStore = { 0f, 0f }; - { - final MonitorDevice monitor = winctx.window.getMainMonitor(); - Assert.assertNotNull(monitor); - System.err.println(monitor); - monitor.getPixelsPerMM(ppmmStore); - } - final GLUniformData rulerPixFreq = new GLUniformData("gcu_RulerPixFreq", 2, Buffers.newDirectFloatBuffer(2)); - final FloatBuffer rulerPixFreqV = (FloatBuffer) rulerPixFreq.getBuffer(); - rulerPixFreqV.put(0, ppmmStore[0] * 10.0f); - rulerPixFreqV.put(1, ppmmStore[1] * 10.0f); - st.ownUniform(rulerPixFreq); - st.uniform(gl, rulerPixFreq); - Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); - System.err.println("Screen pixel/cm "+rulerPixFreqV.get(0)+", "+rulerPixFreqV.get(1)); - - final GLArrayDataServer vertices0 = GLArrayDataServer.createGLSL("gca_Vertices", 3, GL.GL_FLOAT, false, 4, GL.GL_STATIC_DRAW); - 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); - - // 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.gluPerspective(45.0F, (float) drawable.getWidth() / (float) drawable.getHeight(), 1.0F, 100.0F); - pmvMatrix.glMatrixMode(PMVMatrix.GL_MODELVIEW); - pmvMatrix.glLoadIdentity(); - // pmvMatrix.glTranslatef(0, 0, -6); - // pmvMatrix.glRotatef(45f, 1f, 0f, 0f); - st.uniform(gl, pmvMatrixUniform); - gl.glViewport(0, 0, drawable.getSurfaceWidth(), drawable.getSurfaceHeight()); - Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); - - for(int i=0; i<10; i++) { - vertices0.enableBuffer(gl, true); - gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); - gl.glDrawArrays(GL.GL_TRIANGLE_STRIP, 0, 4); - vertices0.enableBuffer(gl, false); - drawable.swapBuffers(); - Thread.sleep(durationPerTest/10); - } + private void setTitle(final Window win) { + final float[] sDPI = win.getPixelsPerMM(new float[2]); + sDPI[0] *= 25.4f; + sDPI[1] *= 25.4f; + win.setTitle("GLWindow: win: "+win.getBounds()+", pix: "+win.getSurfaceWidth()+"x"+win.getSurfaceHeight()+", sDPI "+sDPI[0]+" x "+sDPI[1]); + } + + private void runTestGL() throws InterruptedException { + final GLWindow glWindow = GLWindow.create(new GLCapabilities(GLProfile.getGL2ES2())); + Assert.assertNotNull(glWindow); + glWindow.setSurfaceScale(reqSurfacePixelScale); + final int[] valReqSurfacePixelScale = glWindow.getRequestedSurfaceScale(new int[2]); + glWindow.setSize(640, 480); + + glWindow.addGLEventListener(new GLEventListener() { + final ShaderState st = new ShaderState(); + final PMVMatrix pmvMatrix = new PMVMatrix(); + final GLUniformData pmvMatrixUniform = new GLUniformData("gcu_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf()); + final GLArrayDataServer vertices0 = GLArrayDataServer.createGLSL("gca_Vertices", 3, GL.GL_FLOAT, false, 4, GL.GL_STATIC_DRAW); + final GLUniformData rulerPixFreq = new GLUniformData("gcu_RulerPixFreq", 2, Buffers.newDirectFloatBuffer(2)); + + @Override + public void init(GLAutoDrawable drawable) { + final GL2ES2 gl = drawable.getGL().getGL2ES2(); + + Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); + + final ShaderCode vp0 = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, RedSquareES2.class, "shader", + "shader/bin", "default", true); + final ShaderCode fp0 = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, RedSquareES2.class, "shader", + "shader/bin", "ruler", true); + vp0.defaultShaderCustomization(gl, true, true); + fp0.defaultShaderCustomization(gl, true, true); + + 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, true); + + Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); + st.ownUniform(pmvMatrixUniform); + st.uniform(gl, pmvMatrixUniform); + Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); + + final GLUniformData rulerColor= new GLUniformData("gcu_RulerColor", 3, Buffers.newDirectFloatBuffer(3)); + final FloatBuffer rulerColorV = (FloatBuffer) rulerColor.getBuffer(); + rulerColorV.put(0, 0.5f); + rulerColorV.put(1, 0.5f); + rulerColorV.put(2, 0.5f); + st.ownUniform(rulerColor); + st.uniform(gl, rulerColor); + Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); + + st.ownUniform(rulerPixFreq); + + 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); + + // misc GL setup + gl.glClearColor(1, 1, 1, 1); + gl.glEnable(GL2ES2.GL_DEPTH_TEST); + Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); + } - long t2 = System.nanoTime(); + @Override + public void dispose(GLAutoDrawable drawable) { + } + + @Override + public void display(GLAutoDrawable drawable) { + final GL2ES2 gl = drawable.getGL().getGL2ES2(); + vertices0.enableBuffer(gl, true); + gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); + gl.glDrawArrays(GL.GL_TRIANGLE_STRIP, 0, 4); + vertices0.enableBuffer(gl, false); + } + + @Override + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { + final GL2ES2 gl = drawable.getGL().getGL2ES2(); + pmvMatrix.glMatrixMode(PMVMatrix.GL_PROJECTION); + pmvMatrix.glLoadIdentity(); + pmvMatrix.glOrthof(0f, 1f, 0f, 1f, -10f, 10f); + // pmvMatrix.gluPerspective(45.0F, (float) drawable.getWidth() / (float) drawable.getHeight(), 1.0F, 100.0F); + pmvMatrix.glMatrixMode(PMVMatrix.GL_MODELVIEW); + pmvMatrix.glLoadIdentity(); + // pmvMatrix.glTranslatef(0, 0, -6); + // pmvMatrix.glRotatef(45f, 1f, 0f, 0f); + st.uniform(gl, pmvMatrixUniform); + + final float[] ppmmStore = glWindow.getPixelsPerMM(new float[2]); + final FloatBuffer rulerPixFreqV = (FloatBuffer) rulerPixFreq.getBuffer(); + rulerPixFreqV.put(0, ppmmStore[0] * 10.0f); + rulerPixFreqV.put(1, ppmmStore[1] * 10.0f); + st.uniform(gl, rulerPixFreq); + System.err.println("Screen pixel/cm "+rulerPixFreqV.get(0)+", "+rulerPixFreqV.get(1)); + } + + }); + final SnapshotGLEventListener snap = new SnapshotGLEventListener(); + glWindow.addGLEventListener(snap); + glWindow.addKeyListener(new KeyAdapter() { + @Override + public void keyPressed(final KeyEvent e) { + if( e.isAutoRepeat() ) { + return; + } + if(e.getKeyChar()=='x') { + final int[] hadSurfacePixelScale = glWindow.getCurrentSurfaceScale(new int[2]); + final int[] reqSurfacePixelScale; + if( hadSurfacePixelScale[0] == ScalableSurface.IDENTITY_PIXELSCALE ) { + reqSurfacePixelScale = new int[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE }; + } else { + reqSurfacePixelScale = new int[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE }; + } + System.err.println("[set PixelScale pre]: had "+hadSurfacePixelScale[0]+"x"+hadSurfacePixelScale[1]+" -> req "+reqSurfacePixelScale[0]+"x"+reqSurfacePixelScale[1]); + snap.setMakeSnapshot(); + glWindow.setSurfaceScale(reqSurfacePixelScale); + final int[] valReqSurfacePixelScale = glWindow.getRequestedSurfaceScale(new int[2]); + final int[] hasSurfacePixelScale = glWindow.getCurrentSurfaceScale(new int[2]); + final int[] nativeSurfacePixelScale = glWindow.getNativeSurfaceScale(new int[2]); + System.err.println("[set PixelScale post]: "+hadSurfacePixelScale[0]+"x"+hadSurfacePixelScale[1]+" (had) -> "+ + reqSurfacePixelScale[0]+"x"+reqSurfacePixelScale[1]+" (req) -> "+ + valReqSurfacePixelScale[0]+"x"+valReqSurfacePixelScale[1]+" (val) -> "+ + hasSurfacePixelScale[0]+"x"+hasSurfacePixelScale[1]+" (has), "+ + nativeSurfacePixelScale[0]+"x"+nativeSurfacePixelScale[1]+" (native)"); + setTitle(glWindow); + } + } + }); + + glWindow.setVisible(true); - NEWTGLContext.destroyWindow(winctx); + final int[] hasSurfacePixelScale1 = glWindow.getCurrentSurfaceScale(new int[2]); + System.err.println("HiDPI PixelScale: "+reqSurfacePixelScale[0]+"x"+reqSurfacePixelScale[1]+" (req) -> "+ + valReqSurfacePixelScale[0]+"x"+valReqSurfacePixelScale[1]+" (val) -> "+ + hasSurfacePixelScale1[0]+"x"+hasSurfacePixelScale1[1]+" (has)"); + setTitle(glWindow); - long t3 = System.nanoTime(); + snap.setMakeSnapshot(); + glWindow.display(); - System.err.println("t1-t0: "+ (t1-t0)/1e6 +"ms"); - System.err.println("t3-t0: "+ (t3-t0)/1e6 +"ms"); - System.err.println("t3-t2: "+ (t3-t2)/1e6 +"ms"); + Thread.sleep(durationPerTest); + + glWindow.destroy(); + + } + + @Test + public void test01_PSA() throws InterruptedException { + runTestGL(); + } + + @Test + public void test99_PS1() throws InterruptedException, InvocationTargetException { + if(manualTest) return; + reqSurfacePixelScale[0] = ScalableSurface.IDENTITY_PIXELSCALE; + reqSurfacePixelScale[1] = ScalableSurface.IDENTITY_PIXELSCALE; + runTestGL(); } public static void main(String args[]) throws IOException { @@ -177,6 +240,13 @@ public class TestRulerNEWT01 extends UITestCase { for(int i=0; i<args.length; i++) { if(args[i].equals("-time")) { durationPerTest = MiscUtils.atoi(args[++i], (int)durationPerTest); + } else if(args[i].equals("-pixelScale")) { + i++; + final int pS = MiscUtils.atoi(args[i], reqSurfacePixelScale[0]); + reqSurfacePixelScale[0] = pS; + reqSurfacePixelScale[1] = pS; + } else if(args[i].equals("-manual")) { + manualTest = true; } } String tstname = TestRulerNEWT01.class.getName(); |