From 4686a652d821efe04045333026be79270bc19bfd Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Mon, 9 Jun 2014 03:58:37 +0200 Subject: 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 .. --- .../classes/javax/media/opengl/awt/GLCanvas.java | 12 +- .../classes/javax/media/opengl/awt/GLJPanel.java | 26 +- .../com/jogamp/nativewindow/awt/JAWTWindow.java | 23 +- .../javax/media/nativewindow/ScalableSurface.java | 21 +- .../javax/media/nativewindow/util/Dimension.java | 6 +- .../jogamp/nativewindow/SurfaceScaleUtils.java | 31 +-- .../jogamp/nativewindow/WrappedSurface.java | 6 + .../classes/com/jogamp/newt/MonitorDevice.java | 22 +- src/newt/classes/com/jogamp/newt/Window.java | 21 ++ .../classes/com/jogamp/newt/opengl/GLWindow.java | 10 + src/newt/classes/jogamp/newt/WindowImpl.java | 35 ++- .../jogamp/newt/driver/macosx/WindowDriver.java | 37 +-- src/newt/native/NewtMacWindow.m | 10 +- .../test/junit/graph/TestTextRendererNEWT00.java | 5 +- .../test/junit/graph/TextRendererGLELBase.java | 3 +- .../graph/demos/GPUTextRendererListenerBase01.java | 2 +- .../junit/graph/demos/GPUUISceneGLListener0A.java | 18 +- .../graph/demos/GPUUISceneNewtCanvasAWTDemo.java | 14 + .../jogl/demos/es2/newt/TestGearsES2NEWT.java | 6 +- .../demos/es2/newt/TestGearsES2NewtCanvasAWT.java | 5 +- .../test/junit/jogl/glsl/TestRulerNEWT01.java | 294 +++++++++++++-------- 21 files changed, 400 insertions(+), 207 deletions(-) (limited to 'src') 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 monitor surface resolution in pixels. + *

+ * The native pixel scale maybe used to determine the proper dpi + * value of this {@link NativeSurface}: + *

+   *    surfacePpMM = monitorPpMM * currentSurfaceScale / nativeSurfaceScale,
+   *    with PpMM == pixel per millimeter
+   * 
+ *

+ * + * @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 prePixelScale 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 pixels per millimeter value according to current {@link MonitorMode} - * {@link SurfaceSize#getResolution() SurfaceSize's resolution} in the given storage ppmmStore. + * Returns the pixels per millimeter value according to the current {@link MonitorMode mode}'s + * {@link SurfaceSize#getResolution() surface resolution}. *

* To convert the result to dpi, i.e. dots-per-inch, multiply both components with 25.4f. *

+ * @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 pixels per millimeter value according to the given {@link MonitorMode} - * {@link SurfaceSize#getResolution() SurfaceSize's resolution} in the given storage ppmmStore. + * Returns the pixels per millimeter value according to the given {@link MonitorMode mode}'s + * {@link SurfaceSize#getResolution() surface resolution}. *

* To convert the result to dpi, i.e. dots-per-inch, multiply both components with 25.4f. *

+ * @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: @@ -253,6 +254,26 @@ public interface Window extends NativeWindow, WindowClosingProtocol, ScalableSur */ Rectangle getBounds(); + /** + * Returns the pixels per millimeter of this window's {@link NativeSurface} + * according to the {@link #getMainMonitor() main monitor}'s current {@link MonitorMode mode}'s + * {@link SurfaceSize#getResolution() surface resolution}. + *

+ * Method takes the {@link #getCurrentSurfaceScale(int[]) current surface-scale} and {@link #getNativeSurfaceScale(int[]) native surface-scale} + * into account, i.e.: + *

+     *    surfacePpMM = monitorPpMM * currentSurfaceScale / nativeSurfaceScale,
+     *    with PpMM == pixel per millimeter
+     * 
+ *

+ *

+ * To convert the result to dpi, i.e. dots-per-inch, multiply both components with 25.4f. + *

+ * @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. * 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 @@ -403,6 +403,16 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind return window.getCurrentSurfaceScale(result); } + @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