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/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 ++++++++++++---------- 5 files changed, 91 insertions(+), 34 deletions(-) (limited to 'src/newt/classes') 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 -- cgit v1.2.3