diff options
author | Sven Gothel <[email protected]> | 2015-01-27 00:49:51 +0100 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2015-01-27 00:49:51 +0100 |
commit | 6516a52d3da5cced924db63b64af911d55355325 (patch) | |
tree | fe4404bbd72d4db624722459c76a520019cfb4ca | |
parent | 26f965bbe7b40968158901c3f4ef2f54e821ac70 (diff) |
Bug 1120 - Refine HiDPI Support ( Part-2 ) (API CHANGE)
- Use float[2] for pixel-scale.
Utilize simple integer rounding:
int-pixel-units = (int) ( int-window-units * pixel-scale + 0.5f )
- Provide minimum and maximum allowed pixel-scale values
to be set by platform, supporting generic pixel-scale validation.
- Remove 'OSXUtil.GetPixelScale(final RectangleImmutable r, final int[] screenIndexOut)',
implementation for all platforms would cause huge redundancy of
Screen and MonitorDevice code (duplication of NEWT).
- instead, add 'float[2] pixelScale' to NEWT's MonitorDevice
- Detect change of pixel-scale and propagate accordingly.
This allows GLCanvas, GLJPanel and NewtCanvasAWT instances
to be dragged between monitor devices w/ different pixel-scale.
- OSX: Handle native triggered reshape events off-thread to avoid EDT congestion
due to locked window when consuming deferred events on EDT.
46 files changed, 968 insertions, 676 deletions
diff --git a/make/scripts/tests.sh b/make/scripts/tests.sh index 8711384de..5c440501d 100644 --- a/make/scripts/tests.sh +++ b/make/scripts/tests.sh @@ -161,7 +161,7 @@ function jrun() { #D_ARGS="-Djogl.debug.GLContext -Djogl.debug.GLDrawable -Dnativewindow.debug.ProxySurface -Djogl.debug.GLProfile" #D_ARGS="-Djogl.disable.surfacelesscontext -Djogl.debug.GLContext -Djogl.debug.GLDrawable -Djogl.debug.GLJPanel -Djogl.debug.DebugGL" #D_ARGS="-Djogl.debug.GLContext -Djogl.debug.GLJPanel -Djogl.debug.DebugGL" - D_ARGS="-Djogl.debug.GLContext -Djogl.debug.GLJPanel" + #D_ARGS="-Djogl.debug.GLContext -Djogl.debug.GLJPanel" #D_ARGS="-Djogl.debug.GLDrawable -Djogl.debug.GLContext -Djogl.debug.GLJPanel" #D_ARGS="-Djogl.debug.GLJPanel" #D_ARGS="-Djogl.debug.GLContext.NoProfileAliasing" @@ -231,7 +231,7 @@ function jrun() { #D_ARGS="-Dnewt.debug.EDT" #D_ARGS="-Dnewt.debug.Window -Dnewt.debug.Display -Dnewt.debug.EDT -Djogl.debug.GLContext" #D_ARGS="-Dnewt.debug.Window -Djogl.debug.Animator -Dnewt.debug.Screen" - #D_ARGS="-Dnativewindow.debug.JAWT -Dnewt.debug.Window -Djogl.debug.GLJPanel -Djogl.debug.GLCanvas" + D_ARGS="-Dnativewindow.debug.JAWT -Dnewt.debug.Window -Djogl.debug.GLJPanel -Djogl.debug.GLCanvas" #D_ARGS="-Dnewt.debug.Window.KeyEvent" #D_ARGS="-Dnewt.debug.Window.MouseEvent" #D_ARGS="-Dnewt.debug.Window.MouseEvent -Dnewt.debug.Window.KeyEvent" diff --git a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java index a648e3bf6..a3b84a838 100644 --- a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java +++ b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java @@ -178,9 +178,10 @@ 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 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 }; + private final float[] minPixelScale = new float[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE }; + private final float[] maxPixelScale = new float[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE }; + private final float[] hasPixelScale = new float[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE }; + final float[] reqPixelScale = new float[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE }; // copy of the cstr args, mainly for recreation private final GLCapabilitiesImmutable capsReqUser; @@ -642,38 +643,73 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing } @Override - public final void setSurfaceScale(final int[] pixelScale) { - SurfaceScaleUtils.validateReqPixelScale(reqPixelScale, pixelScale, DEBUG ? getClass().getSimpleName() : null); - if( isRealized() ) { - final ScalableSurface ns = jawtWindow; - if( null != ns ) { - ns.setSurfaceScale(reqPixelScale); - final int hadPixelScaleX = hasPixelScale[0]; - final int hadPixelScaleY = hasPixelScale[1]; - ns.getCurrentSurfaceScale(hasPixelScale); - if( hadPixelScaleX != hasPixelScale[0] || hadPixelScaleY != hasPixelScale[1] ) { - reshapeImpl(getWidth(), getHeight()); - display(); - } - } + public final boolean setSurfaceScale(final float[] pixelScale) { + System.arraycopy(pixelScale, 0, reqPixelScale, 0, 2); + if( isRealized() && isShowing ) { + Threading.invoke(true, setSurfaceScaleOnEDTAction, getTreeLock()); + return true; + } else { + return false; + } + } + private final Runnable setSurfaceScaleOnEDTAction = new Runnable() { + @Override + public void run() { + final RecursiveLock _lock = lock; + _lock.lock(); + try { + if( null != drawable && drawable.isRealized() ) { + if( setSurfaceScaleImpl(jawtWindow) ) { + reshapeImpl(getWidth(), getHeight()); + if( !helper.isAnimatorAnimatingOnOtherThread() ) { + helper.invokeGL(drawable, context, displayAction, initAction); // display + } + } + } + } finally { + _lock.unlock(); + } + } }; + private final boolean setSurfaceScaleImpl(final ScalableSurface ns) { + if( ns.setSurfaceScale(reqPixelScale) ) { + ns.getCurrentSurfaceScale(hasPixelScale); + return true; + } else { + return false; + } + } + + private final boolean updatePixelScale() { + if( jawtWindow.hasPixelScaleChanged() ) { + jawtWindow.getMaximumSurfaceScale(maxPixelScale); + jawtWindow.getMinimumSurfaceScale(minPixelScale); + return setSurfaceScaleImpl(jawtWindow); + } else { + return false; } } @Override - public final int[] getRequestedSurfaceScale(final int[] result) { + public final float[] getRequestedSurfaceScale(final float[] result) { System.arraycopy(reqPixelScale, 0, result, 0, 2); return result; } @Override - public final int[] getCurrentSurfaceScale(final int[] result) { + public final float[] getCurrentSurfaceScale(final float[] result) { System.arraycopy(hasPixelScale, 0, result, 0, 2); return result; } @Override - public int[] getNativeSurfaceScale(final int[] result) { - System.arraycopy(nativePixelScale, 0, result, 0, 2); + public float[] getMinimumSurfaceScale(final float[] result) { + System.arraycopy(minPixelScale, 0, result, 0, 2); + return result; + } + + @Override + public float[] getMaximumSurfaceScale(final float[] result) { + System.arraycopy(maxPixelScale, 0, result, 0, 2); return result; } @@ -681,13 +717,14 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing if ( !Beans.isDesignTime() ) { jawtWindow = (JAWTWindow) NativeWindowFactory.getNativeWindow(this, awtConfig); jawtWindow.setShallUseOffscreenLayer(shallUseOffscreenLayer); - jawtWindow.setSurfaceScale(reqPixelScale); jawtWindow.lockSurface(); try { + jawtWindow.setSurfaceScale(reqPixelScale); drawable = (GLDrawableImpl) GLDrawableFactory.getFactory(capsReqUser.getGLProfile()).createGLDrawable(jawtWindow); createContextImpl(drawable); jawtWindow.getCurrentSurfaceScale(hasPixelScale); - jawtWindow.getNativeSurfaceScale(nativePixelScale); + jawtWindow.getMinimumSurfaceScale(minPixelScale); + jawtWindow.getMaximumSurfaceScale(maxPixelScale); } finally { jawtWindow.unlockSurface(); } @@ -785,10 +822,9 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing reshapeImpl(width, height); } } - private void reshapeImpl(final int width, final int height) { - final int scaledWidth = width * hasPixelScale[0]; - final int scaledHeight = height * hasPixelScale[1]; + final int scaledWidth = SurfaceScaleUtils.scale(width, hasPixelScale[0]); + final int scaledHeight = SurfaceScaleUtils.scale(height, hasPixelScale[1]); if(DEBUG) { final NativeSurface ns = getNativeSurface(); @@ -1187,12 +1223,12 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing @Override public int getSurfaceWidth() { - return getWidth() * hasPixelScale[0]; + return SurfaceScaleUtils.scale(getWidth(), hasPixelScale[0]); } @Override public int getSurfaceHeight() { - return getHeight() * hasPixelScale[1]; + return SurfaceScaleUtils.scale(getHeight(), hasPixelScale[1]); } @Override @@ -1239,7 +1275,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing // Internals only below this point // - private final String getPixelScaleStr() { return hasPixelScale[0]+"x"+hasPixelScale[1]; } + private final String getPixelScaleStr() { return "["+hasPixelScale[0]+", "+hasPixelScale[1]+"]"; } private final Runnable destroyOnEDTAction = new Runnable() { @Override @@ -1339,8 +1375,10 @@ 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; + minPixelScale[0] = ScalableSurface.IDENTITY_PIXELSCALE; + minPixelScale[1] = ScalableSurface.IDENTITY_PIXELSCALE; + maxPixelScale[0] = ScalableSurface.IDENTITY_PIXELSCALE; + maxPixelScale[1] = ScalableSurface.IDENTITY_PIXELSCALE; if(null != awtConfig) { final AbstractGraphicsConfiguration aconfig = awtConfig.getNativeGraphicsConfiguration(); @@ -1391,6 +1429,9 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing _lock.lock(); try { if( null != drawable && drawable.isRealized() ) { + if( GLCanvas.this.updatePixelScale() ) { + GLCanvas.this.reshapeImpl(getWidth(), getHeight()); + } helper.invokeGL(drawable, context, displayAction, initAction); } } finally { diff --git a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java index 6e9e28c19..65c4c5537 100644 --- a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java +++ b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java @@ -262,9 +262,10 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing private boolean handleReshape = false; private boolean sendReshape = true; - 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 }; + private final float[] minPixelScale = new float[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE }; + private final float[] maxPixelScale = new float[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE }; + private final float[] hasPixelScale = new float[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE }; + private final float[] reqPixelScale = new float[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE }; /** For handling reshape events lazily: reshapeWidth -> panelWidth -> backend.width in pixel units (scaled) */ private int reshapeWidth; @@ -450,20 +451,20 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing @Override public void display() { - if( isShowing || ( printActive && isVisible() ) ) { - if (EventQueue.isDispatchThread()) { - // Want display() to be synchronous, so call paintImmediately() - paintImmediately(0, 0, getWidth(), getHeight()); - } else { - // Multithreaded redrawing of Swing components is not allowed, - // so do everything on the event dispatch thread - try { - EventQueue.invokeAndWait(paintImmediatelyAction); - } catch (final Exception e) { - throw new GLException(e); + if( isShowing || ( printActive && isVisible() ) ) { + if (EventQueue.isDispatchThread()) { + // Want display() to be synchronous, so call paintImmediately() + paintImmediatelyAction.run(); + } else { + // Multithreaded redrawing of Swing components is not allowed, + // so do everything on the event dispatch thread + try { + EventQueue.invokeAndWait(paintImmediatelyAction); + } catch (final Exception e) { + throw new GLException(e); + } } - } - } + } } protected void dispose(final Runnable post) { @@ -556,6 +557,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing // re-creating it -- tricky to do properly while the context is // current if( !printActive ) { + updatePixelScale(backend); if ( handleReshape ) { handleReshape = false; sendReshape = handleReshape(); @@ -579,36 +581,76 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing } @Override - public final void setSurfaceScale(final int[] pixelScale) { // HiDPI support - SurfaceScaleUtils.validateReqPixelScale(reqPixelScale, pixelScale, DEBUG ? getClass().getSimpleName() : null); - final int hadPixelScaleX = hasPixelScale[0]; - final int hadPixelScaleY = hasPixelScale[1]; - SurfaceScaleUtils.computePixelScale(hasPixelScale, hasPixelScale, reqPixelScale, nativePixelScale, DEBUG ? getClass().getSimpleName() : null); - if( hadPixelScaleX != hasPixelScale[0] || hadPixelScaleY != hasPixelScale[1] ) { - reshapeImpl(getWidth(), getHeight()); - final Backend b = backend; - if ( isInitialized && null != b ) { - updateWrappedSurfaceScale(b.getDrawable()); - display(); + public final boolean setSurfaceScale(final float[] pixelScale) { // HiDPI support + System.arraycopy(pixelScale, 0, reqPixelScale, 0, 2); + final Backend b = backend; + if ( isInitialized && null != b && isShowing ) { + if( isShowing || ( printActive && isVisible() ) ) { + if (EventQueue.isDispatchThread()) { + setSurfaceScaleAction.run(); + } else { + try { + EventQueue.invokeAndWait(setSurfaceScaleAction); + } catch (final Exception e) { + throw new GLException(e); + } + } } + return true; + } else { + return false; + } + } + private final Runnable setSurfaceScaleAction = new Runnable() { + @Override + public void run() { + final Backend b = backend; + if( null != b && setSurfaceScaleImpl(b) ) { + if( !helper.isAnimatorAnimatingOnOtherThread() ) { + paintImmediatelyAction.run(); // display + } + } + } + }; + + private final boolean setSurfaceScaleImpl(final Backend b) { + if( SurfaceScaleUtils.setNewPixelScale(hasPixelScale, hasPixelScale, reqPixelScale, minPixelScale, maxPixelScale, DEBUG ? getClass().getSimpleName() : null) ) { + reshapeImpl(getWidth(), getHeight()); + updateWrappedSurfaceScale(b.getDrawable()); + return true; + } + return false; + } + + private final boolean updatePixelScale(final Backend b) { + if( JAWTUtil.getPixelScale(getGraphicsConfiguration(), minPixelScale, maxPixelScale) ) { + return setSurfaceScaleImpl(b); + } else { + return false; } } @Override - public final int[] getRequestedSurfaceScale(final int[] result) { + public final float[] getRequestedSurfaceScale(final float[] result) { System.arraycopy(reqPixelScale, 0, result, 0, 2); return result; } @Override - public final int[] getCurrentSurfaceScale(final int[] result) { + public final float[] getCurrentSurfaceScale(final float[] result) { System.arraycopy(hasPixelScale, 0, result, 0, 2); return result; } @Override - public int[] getNativeSurfaceScale(final int[] result) { - System.arraycopy(nativePixelScale, 0, result, 0, 2); + public float[] getMinimumSurfaceScale(final float[] result) { + System.arraycopy(minPixelScale, 0, result, 0, 2); + return result; + } + + @Override + public float[] getMaximumSurfaceScale(final float[] result) { + System.arraycopy(maxPixelScale, 0, result, 0, 2); return result; } @@ -624,12 +666,8 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing awtWindowClosingProtocol.addClosingListener(); // HiDPI support - { - final int ps = JAWTUtil.getPixelScale(getGraphicsConfiguration()); - nativePixelScale[0] = ps; - nativePixelScale[1] = ps; - } - SurfaceScaleUtils.computePixelScale(hasPixelScale, hasPixelScale, reqPixelScale, nativePixelScale, DEBUG ? getClass().getSimpleName() : null); + JAWTUtil.getPixelScale(getGraphicsConfiguration(), minPixelScale, maxPixelScale); + SurfaceScaleUtils.setNewPixelScale(hasPixelScale, hasPixelScale, reqPixelScale, minPixelScale, maxPixelScale, DEBUG ? getClass().getSimpleName() : null); if (DEBUG) { System.err.println(getThreadName()+": GLJPanel.addNotify()"); @@ -649,8 +687,10 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing dispose(null); hasPixelScale[0] = ScalableSurface.IDENTITY_PIXELSCALE; hasPixelScale[1] = ScalableSurface.IDENTITY_PIXELSCALE; - nativePixelScale[0] = ScalableSurface.IDENTITY_PIXELSCALE; - nativePixelScale[1] = ScalableSurface.IDENTITY_PIXELSCALE; + minPixelScale[0] = ScalableSurface.IDENTITY_PIXELSCALE; + minPixelScale[1] = ScalableSurface.IDENTITY_PIXELSCALE; + maxPixelScale[0] = ScalableSurface.IDENTITY_PIXELSCALE; + maxPixelScale[1] = ScalableSurface.IDENTITY_PIXELSCALE; super.removeNotify(); } @@ -670,8 +710,8 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing } private void reshapeImpl(final int width, final int height) { - final int scaledWidth = width * hasPixelScale[0]; - final int scaledHeight = height * hasPixelScale[1]; + final int scaledWidth = SurfaceScaleUtils.scale(width, hasPixelScale[0]); + final int scaledHeight = SurfaceScaleUtils.scale(height, hasPixelScale[1]); if( !printActive && ( handleReshape || scaledWidth != panelWidth || scaledHeight != panelHeight ) ) { reshapeWidth = scaledWidth; reshapeHeight = scaledHeight; @@ -826,8 +866,8 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing // trigger reshape, i.e. gl-viewport and -listener - this component might got resized! final int awtWidth = GLJPanel.this.getWidth(); final int awtHeight= GLJPanel.this.getHeight(); - final int scaledAWTWidth = awtWidth * hasPixelScale[0]; - final int scaledAWTHeight= awtHeight * hasPixelScale[1]; + final int scaledAWTWidth = SurfaceScaleUtils.scale(awtWidth, hasPixelScale[0]); + final int scaledAWTHeight= SurfaceScaleUtils.scale(awtHeight, hasPixelScale[1]); final GLDrawable drawable = GLJPanel.this.getDelegatedDrawable(); if( scaledAWTWidth != panelWidth || scaledAWTHeight != panelHeight || drawable.getSurfaceWidth() != panelWidth || drawable.getSurfaceHeight() != panelHeight ) { @@ -1342,7 +1382,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing } } - private final String getPixelScaleStr() { return hasPixelScale[0]+"x"+hasPixelScale[1]; } + private final String getPixelScaleStr() { return "["+hasPixelScale[0]+", "+hasPixelScale[1]+"]"; } @Override public WindowClosingMode getDefaultCloseOperation() { @@ -2058,7 +2098,9 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.doPaintComponent.drawImage: - frameCount "+frameCount); } // Draw resulting image in one shot - g.drawImage(alignedImage, 0, 0, alignedImage.getWidth()/hasPixelScale[0], alignedImage.getHeight()/hasPixelScale[1], null); // Null ImageObserver since image data is ready. + g.drawImage(alignedImage, 0, 0, + SurfaceScaleUtils.scaleInv(alignedImage.getWidth(), hasPixelScale[0]), + SurfaceScaleUtils.scaleInv(alignedImage.getHeight(), hasPixelScale[1]), null); // Null ImageObserver since image data is ready. } frameCount++; } diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java b/src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java index 32e4add75..97dba9598 100644 --- a/src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java +++ b/src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java @@ -47,6 +47,8 @@ import com.jogamp.nativewindow.MutableGraphicsConfiguration; import java.awt.Component; import java.awt.Container; import java.awt.Cursor; +import java.awt.EventQueue; +import java.awt.GraphicsConfiguration; import java.awt.Window; import java.awt.event.ComponentEvent; import java.awt.event.ComponentListener; @@ -103,10 +105,11 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface, protected Insets insets; private volatile long offscreenSurfaceLayer; - 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 final float[] minPixelScale = new float[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE }; + private final float[] maxPixelScale = new float[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE }; + private final float[] hasPixelScale = new float[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE }; + private final float[] reqPixelScale = new float[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE }; + private volatile boolean hasPixelScaleChanged = false; private long drawable_old; /** @@ -269,38 +272,41 @@ 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; + minPixelScale[0] = ScalableSurface.IDENTITY_PIXELSCALE; + minPixelScale[1] = ScalableSurface.IDENTITY_PIXELSCALE; + maxPixelScale[0] = ScalableSurface.IDENTITY_PIXELSCALE; + maxPixelScale[1] = ScalableSurface.IDENTITY_PIXELSCALE; + hasPixelScaleChanged = false; } protected abstract void invalidateNative(); - /** - * {@inheritDoc} - * <p> - * Per default impl. only works for not yet {@link #isRealized() realized} instances, - * current exception OSX. - * </p> - */ @Override - public void setSurfaceScale(final int[] pixelScale) { - SurfaceScaleUtils.validateReqPixelScale(reqPixelScale, pixelScale, DEBUG ? getClass().getSimpleName() : null); + public boolean setSurfaceScale(final float[] pixelScale) { + System.arraycopy(pixelScale, 0, reqPixelScale, 0, 2); + return false; } @Override - public final int[] getRequestedSurfaceScale(final int[] result) { + public final float[] getRequestedSurfaceScale(final float[] result) { System.arraycopy(reqPixelScale, 0, result, 0, 2); return result; } @Override - public final int[] getCurrentSurfaceScale(final int[] result) { + public final float[] getCurrentSurfaceScale(final float[] result) { System.arraycopy(hasPixelScale, 0, result, 0, 2); return result; } @Override - public final int[] getNativeSurfaceScale(final int[] result) { - System.arraycopy(nativePixelScale, 0, result, 0, 2); + public float[] getMinimumSurfaceScale(final float[] result) { + System.arraycopy(minPixelScale, 0, result, 0, 2); + return result; + } + + @Override + public final float[] getMaximumSurfaceScale(final float[] result) { + System.arraycopy(maxPixelScale, 0, result, 0, 2); return result; } @@ -323,31 +329,75 @@ 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; + updatePixelScale(false); + return hasPixelScaleChanged || changedBounds; + } + + /** + * Updates the minimum and maximum pixel-scale values + * and returns {@code true} if they were updated. + * @param clearFlag if {@code true}, the {@code hasPixelScaleChanged} flag will be cleared + * @return {@code true} if values were updated, otherwise {@code false}. + * @see #hasPixelScaleChanged() + */ + public final boolean updatePixelScale(final boolean clearFlag) { + // Using GraphicsConfiguration from component, which may change by moving to diff monitor + if( EventQueue.isDispatchThread() || Thread.holdsLock(component.getTreeLock()) ) { + if( JAWTUtil.getPixelScale(component.getGraphicsConfiguration(), minPixelScale, maxPixelScale) ) { + hasPixelScaleChanged = true; + if( DEBUG ) { + System.err.println("JAWTWindow.updatePixelScale: updated req["+ + reqPixelScale[0]+", "+reqPixelScale[1]+"], min["+ + minPixelScale[0]+", "+minPixelScale[1]+"], max["+ + maxPixelScale[0]+", "+maxPixelScale[1]+"], has["+ + hasPixelScale[0]+", "+hasPixelScale[1]+"]"); + } + } + } + if( clearFlag ) { + final boolean r = hasPixelScaleChanged; + hasPixelScaleChanged = false; + return r; + } else { + return hasPixelScaleChanged; + } + } + + /** + * Returns and clears the {@code hasPixelScaleChanged} flag, as set via {@link #lockSurface()}. + * <p> + * {@code hasPixelScaleChanged} is {@code true}, + * if the {@link #getMinimumSurfaceScale(float[]) minimum} or {@link #getMaximumSurfaceScale(float[]) maximum} + * pixel scale has changed. + * User needs to {@link #setSurfaceScale(float[]) set the current pixel scale} in this case + * using the {@link #getRequestedSurfaceScale(float[]) requested pixel scale} + * to update the surface pixel scale. + * </p> + */ + public final boolean hasPixelScaleChanged() { + final boolean v = hasPixelScaleChanged; + hasPixelScaleChanged = false; + return v; } /** - * Update pixelScale + * set requested pixelScale * @return true if pixelScale has changed, otherwise false */ - protected final boolean updatePixelScale() { - return SurfaceScaleUtils.computePixelScale(hasPixelScale, hasPixelScale, reqPixelScale, nativePixelScale, DEBUG ? getClass().getSimpleName() : null); + protected final boolean setReqPixelScale() { + updatePixelScale(true); + return SurfaceScaleUtils.setNewPixelScale(hasPixelScale, hasPixelScale, reqPixelScale, minPixelScale, maxPixelScale, DEBUG ? getClass().getSimpleName() : null); } /** @return the JAWT_DrawingSurfaceInfo's (JAWT_Rectangle) bounds, updated with lock */ public final RectangleImmutable getBounds() { return bounds; } /** @return the safe pixelScale value for x-direction, i.e. never negative or zero. Updated with lock. */ - protected final int getPixelScaleX() { return hasPixelScale[0]; } + protected final float getPixelScaleX() { return hasPixelScale[0]; } /** @return the safe pixelScale value for y-direction, i.e. never negative or zero. Updated with lock. */ - protected final int getPixelScaleY() { return hasPixelScale[1]; } + protected final float getPixelScaleY() { return hasPixelScale[1]; } @Override public final InsetsImmutable getInsets() { return insets; } @@ -671,26 +721,22 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface, @Override public final int getSurfaceWidth() { - return getWidth() * getPixelScaleX(); + return SurfaceScaleUtils.scale(getWidth(), getPixelScaleX()); } @Override public final int getSurfaceHeight() { - return getHeight() * getPixelScaleY(); + return SurfaceScaleUtils.scale(getHeight(), getPixelScaleY()); } @Override public final int[] convertToWindowUnits(final int[] pixelUnitsAndResult) { - pixelUnitsAndResult[0] /= getPixelScaleX(); - pixelUnitsAndResult[1] /= getPixelScaleY(); - return pixelUnitsAndResult; + return SurfaceScaleUtils.scaleInv(pixelUnitsAndResult, pixelUnitsAndResult, hasPixelScale); } @Override public final int[] convertToPixelUnits(final int[] windowUnitsAndResult) { - windowUnitsAndResult[0] *= getPixelScaleX(); - windowUnitsAndResult[1] *= getPixelScaleY(); - return windowUnitsAndResult; + return SurfaceScaleUtils.scale(windowUnitsAndResult, windowUnitsAndResult, hasPixelScale); } @Override @@ -874,7 +920,7 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface, ", bounds "+bounds+", insets "+insets ); sb.append(", window ["+getX()+"/"+getY()+" "+getWidth()+"x"+getHeight()+ - "], pixels[s "+getPixelScaleX()+"x"+getPixelScaleY()+" -> "+getSurfaceWidth()+"x"+getSurfaceHeight()+"]"+ + "], pixels[scale "+getPixelScaleX()+", "+getPixelScaleY()+" -> "+getSurfaceWidth()+"x"+getSurfaceHeight()+"]"+ ", visible "+component.isVisible()); sb.append(", lockedExt "+isSurfaceLockedByOtherThread()+ ",\n\tconfig "+config+ diff --git a/src/nativewindow/classes/javax/media/nativewindow/NativeSurface.java b/src/nativewindow/classes/javax/media/nativewindow/NativeSurface.java index 4d764dc4f..d5ac56178 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/NativeSurface.java +++ b/src/nativewindow/classes/javax/media/nativewindow/NativeSurface.java @@ -198,6 +198,7 @@ public interface NativeSurface extends SurfaceUpdatedListener { * @param pixelUnitsAndResult int[2] storage holding the pixel units for the x- and y-coord to convert * and the resulting values. * @return result int[2] storage pixelUnitsAndResult for chaining holding the converted values + * @see ScalableSurface */ public int[] convertToWindowUnits(final int[] pixelUnitsAndResult); @@ -206,6 +207,7 @@ public interface NativeSurface extends SurfaceUpdatedListener { * @param windowUnitsAndResult int[2] storage holding the window units for the x- and y-coord to convert * and the resulting values. * @return result int[2] storage windowUnitsAndResult for chaining holding the converted values + * @see ScalableSurface */ public int[] convertToPixelUnits(final int[] windowUnitsAndResult); diff --git a/src/nativewindow/classes/javax/media/nativewindow/ScalableSurface.java b/src/nativewindow/classes/javax/media/nativewindow/ScalableSurface.java index ffd5c224c..0cd2c7961 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/ScalableSurface.java +++ b/src/nativewindow/classes/javax/media/nativewindow/ScalableSurface.java @@ -30,16 +30,17 @@ package javax.media.nativewindow; /** * Adding mutable surface pixel scale property to implementing class, usually to a {@link NativeSurface} implementation, - * see {@link #setSurfaceScale(int[])}. + * see {@link #setSurfaceScale(float[])}. */ public interface ScalableSurface { /** Setting surface-pixel-scale of {@value}, results in same pixel- and window-units. */ - public static final int IDENTITY_PIXELSCALE = 1; + public static final float IDENTITY_PIXELSCALE = 1f; /** Setting surface-pixel-scale of {@value}, results in maximum platform dependent pixel-scale, i.e. pixel-units >> window-units where available. */ - public static final int AUTOMAX_PIXELSCALE = 0; + public static final float AUTOMAX_PIXELSCALE = 0f; /** - * Request a pixel scale in x- and y-direction for the associated {@link NativeSurface}. + * Request a pixel scale in x- and y-direction for the associated {@link NativeSurface}, + * where {@code size_in_pixel_units = pixel_scale * size_in_window_units}. * <p> * Default pixel scale request for both directions is {@link #AUTOMAX_PIXELSCALE}. * </p> @@ -50,48 +51,57 @@ public interface ScalableSurface { * <p> * The <i>requested</i> pixel scale will be validated against platform limits before native scale-setup, * i.e. clipped to {@link #IDENTITY_PIXELSCALE} if not supported or clipped to the platform maximum. - * It can be queried via {@link #getRequestedSurfaceScale(int[])}. + * It can be queried via {@link #getRequestedSurfaceScale(float[])}. * </p> * <p> * The actual <i>realized</i> pixel scale values of the {@link NativeSurface} - * can be queried via {@link #getCurrentSurfaceScale(int[])} or + * can be queried via {@link #getCurrentSurfaceScale(float[])} or * computed via <code>surface.{@link NativeSurface#convertToPixelUnits(int[]) convertToPixelUnits}(new int[] { 1, 1 })</code> * </p> - * @param pixelScale <i>requested</i> surface pixel scale int[2] values for x- and y-direction. + * @param pixelScale <i>requested</i> surface pixel scale float[2] values for x- and y-direction. + * @return {@code true} if the {@link #getCurrentSurfaceScale(float[]) current pixel scale} has changed, otherwise {@code false}. + * @see #getRequestedSurfaceScale(float[]) */ - public void setSurfaceScale(final int[] pixelScale); + public boolean setSurfaceScale(final float[] pixelScale); /** - * Returns the requested pixel scale of the associated {@link NativeSurface}. + * Returns the {@link #setSurfaceScale(float[]) requested} pixel scale of the associated {@link NativeSurface}. * - * @param result int[2] storage for the result - * @return the passed storage containing the requested pixelScale for chaining + * @param result float[2] storage for the result + * @return the passed storage containing the current pixelScale for chaining + * @see #setSurfaceScale(float[]) */ - int[] getRequestedSurfaceScale(final int[] result); + public float[] getRequestedSurfaceScale(final float[] result); /** * Returns the current pixel scale of the associated {@link NativeSurface}. * - * @param result int[2] storage for the result + * @param result float[2] storage for the result * @return the passed storage containing the current pixelScale for chaining */ - public int[] getCurrentSurfaceScale(final int[] result); + public float[] getCurrentSurfaceScale(final float[] result); + + /** + * Returns the minimum pixel scale of the associated {@link NativeSurface}. + * @param result float[2] storage for the result + * @return the passed storage containing the minimum pixelScale for chaining + */ + public float[] getMinimumSurfaceScale(final float[] result); /** - * Returns the native pixel scale of the associated {@link NativeSurface} - * reflecting it's currently bound <i>monitor surface resolution in pixels</i>. + * Returns the maximum pixel scale of the associated {@link NativeSurface}. * <p> - * The native pixel scale maybe used to determine the proper <i>dpi</i> - * value of this {@link NativeSurface}: + * The maximum pixel scale maybe used to determine the proper <i>dpi</i> + * value of the monitor displaying 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 + * @param result float[2] storage for the result + * @return the passed storage containing the maximum pixelScale for chaining */ - public int[] getNativeSurfaceScale(final int[] result); + public float[] getMaximumSurfaceScale(final float[] result); } diff --git a/src/nativewindow/classes/javax/media/nativewindow/util/Point.java b/src/nativewindow/classes/javax/media/nativewindow/util/Point.java index 3576a7dd0..3d416d2f5 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/util/Point.java +++ b/src/nativewindow/classes/javax/media/nativewindow/util/Point.java @@ -145,6 +145,22 @@ public class Point implements Cloneable, PointImmutable { } /** + * Scale this instance's x- and y-components, + * i.e. multiply them by the given scale factors. + * <p> + * The product is rounded back to integer. + * </p> + * @param sx scale factor for x + * @param sy scale factor for y + * @return this instance for scaling + */ + public final Point scale(final float sx, final float sy) { + x = (int)(x * sx + 0.5f); + y = (int)(y * sy + 0.5f); + return this; + } + + /** * Inverse scale this instance's x- and y-components, * i.e. divide them by the given scale factors. * @param sx inverse scale factor for x @@ -156,4 +172,19 @@ public class Point implements Cloneable, PointImmutable { y /= sy ; return this; } + /** + * Inverse scale this instance's x- and y-components, + * i.e. divide them by the given scale factors. + * <p> + * The product is rounded back to integer. + * </p> + * @param sx inverse scale factor for x + * @param sy inverse scale factor for y + * @return this instance for scaling + */ + public final Point scaleInv(final float sx, final float sy) { + x = (int)(x / sx + 0.5f); + y = (int)(y / sy + 0.5f); + return this; + } } diff --git a/src/nativewindow/classes/jogamp/nativewindow/SurfaceScaleUtils.java b/src/nativewindow/classes/jogamp/nativewindow/SurfaceScaleUtils.java index 73413cf59..70eec7b24 100644 --- a/src/nativewindow/classes/jogamp/nativewindow/SurfaceScaleUtils.java +++ b/src/nativewindow/classes/jogamp/nativewindow/SurfaceScaleUtils.java @@ -27,7 +27,6 @@ */ package jogamp.nativewindow; -import javax.media.nativewindow.NativeWindowFactory; import javax.media.nativewindow.ScalableSurface; /** @@ -35,138 +34,162 @@ import javax.media.nativewindow.ScalableSurface; */ public class SurfaceScaleUtils { - private static final int[] PlatformMaxPixelScale; - private static final boolean PlatformUniformPixelScale; - private static final boolean PlatformPixelScaleSupported; + private static final float EPSILON = 1.1920929E-7f; // Float.MIN_VALUE == 1.4e-45f ; double EPSILON 2.220446049250313E-16d - static { - if( NativeWindowFactory.TYPE_MACOSX == NativeWindowFactory.getNativeWindowType(true) ) { - PlatformMaxPixelScale = new int[] { jogamp.nativewindow.macosx.OSXUtil.MAX_PIXELSCALE, jogamp.nativewindow.macosx.OSXUtil.MAX_PIXELSCALE }; - PlatformUniformPixelScale = true; - PlatformPixelScaleSupported = true; - } else { - PlatformMaxPixelScale = new int[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE }; - PlatformUniformPixelScale = false; - PlatformPixelScaleSupported = false; - } + private static boolean isZero(final float a) { + return Math.abs(a) < EPSILON; } /** - * Compute a new valid pixelScale to be used by {@link NativeSurface} implementations, - * based on the given request and surface's pixelScale + * Returns integer rounded product, i.e. {@code (int) ( a * pixelScale + 0.5f )} * - * @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 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 + * @param a the int value + * @param pixelScale the float scale factor + * @return the integer rounded product */ - public static boolean computePixelScale(final 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] = newPixelScaleSafeX; - result[1] = newPixelScaleSafeY; - } else { - result[0] = ScalableSurface.IDENTITY_PIXELSCALE; - result[1] = ScalableSurface.IDENTITY_PIXELSCALE; - } - - 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; + public static int scale(final int a, final float pixelScale) { + return (int) ( a * pixelScale + 0.5f ); } /** - * Validate the given requested pixelScale value pair, i.e. clip it to the - * limits of {@link ScalableSurface#AUTOMAX_PIXELSCALE} and {@link #getPlatformMaxPixelScale(int[])} - * <p> - * To be used by {@link ScalableSurface#setSurfaceScale(int[])} implementations. - * </p> + * Returns integer rounded product, i.e. {@code (int) ( a / pixelScale + 0.5f )} * - * @param result int[2] storage for result - * @param reqPixelScale requested pixelScale - * @param DEBUG_PREFIX if set, dumps debug info on stderr using this prefix + * @param a the int value + * @param pixelScale the float scale factor + * @return the integer rounded product */ - public static void validateReqPixelScale(final int[] result, final int[] reqPixelScale, final String DEBUG_PREFIX) { - final int minPS = Math.min(reqPixelScale[0], reqPixelScale[1]); - if( ScalableSurface.AUTOMAX_PIXELSCALE >= minPS ) { - result[0] = ScalableSurface.AUTOMAX_PIXELSCALE; - result[1] = ScalableSurface.AUTOMAX_PIXELSCALE; - } else if( PlatformUniformPixelScale ) { - final int maxPS = Math.max(reqPixelScale[0], reqPixelScale[1]); - if( maxPS >= PlatformMaxPixelScale[0] ) { - result[0] = PlatformMaxPixelScale[0]; - result[1] = PlatformMaxPixelScale[1]; - } else { - result[0] = maxPS; - result[1] = maxPS; - } - } else { - if( reqPixelScale[0] >= PlatformMaxPixelScale[0] ) { - result[0] = PlatformMaxPixelScale[0]; - } else { - result[0] = reqPixelScale[0]; - } - if( reqPixelScale[1] >= PlatformMaxPixelScale[1] ) { - result[1] = PlatformMaxPixelScale[1]; - } else { - result[1] = reqPixelScale[1]; - } - } - if( null != DEBUG_PREFIX ) { - System.err.println(DEBUG_PREFIX+".validateReqPixelScale: ["+reqPixelScale[0]+"x"+reqPixelScale[1]+" (req), "+ - PlatformMaxPixelScale[0]+"x"+PlatformMaxPixelScale[1]+" (max)] -> "+ - result[0]+"x"+result[1]+" (valid)"); - } + public static int scaleInv(final int a, final float pixelScale) { + return (int) ( a / pixelScale + 0.5f ); } /** - * Replaces {@link ScalableSurface#AUTOMAX_PIXELSCALE} with {@link #getPlatformMaxPixelScale(int[])}, - * for each component. + * Returns integer rounded product, i.e. {@code (int) ( a * pixelScale + 0.5f )} * - * @param pixelScale int[2] value array to be tested and replaced + * @param result the int[2] result, may be {@code a} for in-place operation + * @param a the int[2] values + * @param pixelScale the float[2] scale factors + * @return the result for chaining */ - public static void replaceAutoMaxWithPlatformMax(final int[] pixelScale) { - if( ScalableSurface.AUTOMAX_PIXELSCALE == pixelScale[0] ) { - pixelScale[0] = PlatformMaxPixelScale[0]; - } - if( ScalableSurface.AUTOMAX_PIXELSCALE == pixelScale[1] ) { - pixelScale[1] = PlatformMaxPixelScale[1]; - } + public static int[] scale(final int[] result, final int[] a, final float[] pixelScale) { + result[0] = (int) ( a[0] * pixelScale[0] + 0.5f ); + result[1] = (int) ( a[1] * pixelScale[1] + 0.5f ); + return result; } - /** - * Returns the maximum platform pixelScale + * Returns integer rounded product, i.e. {@code (int) ( a / pixelScale + 0.5f )} + * + * @param result the int[2] result, may be {@code a} for in-place operation + * @param a the int[2] values + * @param pixelScale the float[2] scale factors + * @return the result for chaining */ - public static int[] getPlatformMaxPixelScale(final int[] result) { - System.arraycopy(PlatformMaxPixelScale, 0, result, 0, 2); + public static int[] scaleInv(final int[] result, final int[] a, final float[] pixelScale) { + result[0] = (int) ( a[0] / pixelScale[0] + 0.5f ); + result[1] = (int) ( a[1] / pixelScale[1] + 0.5f ); return result; } /** - * Returns true if platform pixelScale is uniform, i.e. same scale factor for x- and y-direction, otherwise false. + * Method constrains the given pixel-scale within ]0..{@code maxPixelScale}], as described below. + * <p> + * Method returns {@link ScalableSurface#IDENTITY_PIXELSCALE IDENTITY_PIXELSCALE} if: + * <ul> + * <li>{@code pixelScale} ~= {@link ScalableSurface#IDENTITY_PIXELSCALE IDENTITY_PIXELSCALE}</li> + * </ul> + * </p> + * <p> + * Method returns {@code maxPixelScale} if + * <ul> + * <li>{@code pixelScale} ~= {@link ScalableSurface#AUTOMAX_PIXELSCALE AUTOMAX_PIXELSCALE}</li> + * <li>{@code pixelScale} > {@code maxPixelScale}</li> + * <li>{@code pixelScale} ~= {@code maxPixelScale}</li> + * </ul> + * </p> + * <p> + * Method returns {@code minPixelScale} if + * <ul> + * <li>{@code pixelScale} < {@code minPixelScale}</li> + * <li>{@code pixelScale} ~= {@code minPixelScale}</li> + * </ul> + * </p> + * <p> + * Otherwise method returns the given {@code pixelScale}. + * </p> + * <p> + * <i>~=</i> denominates a delta ≤ {@link FloatUtil#EPSILON}. + * </p> + * @param pixelScale pixel-scale to be constrained + * @param minPixelScale minimum pixel-scale + * @param maxPixelScale maximum pixel-scale + * @return the constrained pixel-scale */ - public static boolean isPlatformPixelScaleUniform() { - return PlatformUniformPixelScale; + public static float clampPixelScale(final float pixelScale, final float minPixelScale, final float maxPixelScale) { + if( isZero(pixelScale-ScalableSurface.IDENTITY_PIXELSCALE) ) { + return ScalableSurface.IDENTITY_PIXELSCALE; + } else if( isZero(pixelScale-ScalableSurface.AUTOMAX_PIXELSCALE) || + pixelScale > maxPixelScale || + isZero(pixelScale-maxPixelScale) + ) + { + return maxPixelScale; + } else if( pixelScale < minPixelScale || isZero(pixelScale-minPixelScale) ) + { + return minPixelScale; + } else { + return pixelScale; + } } /** - * Returns whether the platform supports pixelScale + * Method {@link #clampPixelScale(float, float, float) constrains} the given float[2] pixel-scale + * within ]0..{@code maxPixelScale}], as described in {@link #clampPixelScale(float, float, float)}. + * + * @param result float[2] storage for result, maybe same as <code>s</code> for in-place + * @param pixelScale float[2] pixelScale to be constrained + * @param minPixelScale float[2] minimum pixel-scale + * @param maxPixelScale float[2] maximum pixel-scale + * @return the constrained result for chaining */ - public static boolean isPlatformPixelScaleSupported() { - return PlatformPixelScaleSupported; + public static float[] clampPixelScale(final float[] result, final float[] pixelScale, + final float[] minPixelScale, final float[] maxPixelScale) { + result[0] = clampPixelScale(pixelScale[0], minPixelScale[0], maxPixelScale[0]); + result[1] = clampPixelScale(pixelScale[1], minPixelScale[1], maxPixelScale[1]); + return result; } + /** + * Method writes the given float[2] requested pixel-scale {@code reqPixelScale} + * into {@code result} within its constraints ]0..{@code maxPixelScale}], as described in {@link #clampPixelScale(float, float, float)}. + * <p> + * Method only differs from {@link #clampPixelScale(float[], float[], float[], float[])} + * by returning the whether the value has changed, i.e. different from the given {@code prePixelScale}. + * </p> + * + * @param result int[2] storage for result, maybe same as <code>prePixelScale</code> for in-place + * @param prePixelScale float[2] previous pixel-scale + * @param reqPixelScale float[2] requested pixel-scale, validated via {@link #validateReqPixelScale(float[], float[], String)}. + * @param minPixelScale float[2] minimum pixel-scale + * @param maxPixelScale float[2] maximum pixel-scale + * @param DEBUG_PREFIX if set, dumps debug info on stderr using this prefix + * @param newPixelScaleRaw new raw surface pixel-scale + * @return {@code true} if pixel-scale has changed, otherwise {@code false}. + */ + public static boolean setNewPixelScale(final float[] result, + final float[] prePixelScale, final float[] reqPixelScale, + final float[] minPixelScale, final float[] maxPixelScale, + final String DEBUG_PREFIX) { + final float resultX = clampPixelScale(reqPixelScale[0], minPixelScale[0], maxPixelScale[0]); + final float resultY = clampPixelScale(reqPixelScale[1], minPixelScale[1], maxPixelScale[1]); + final boolean changed = resultX != prePixelScale[0] || resultY != prePixelScale[1]; + if( null != DEBUG_PREFIX ) { + System.err.println(DEBUG_PREFIX+".setNewPixelScale: pre["+prePixelScale[0]+", "+prePixelScale[1]+"], req["+ + reqPixelScale[0]+", "+reqPixelScale[1]+"], min["+ + minPixelScale[0]+", "+minPixelScale[1]+"], max["+ + maxPixelScale[0]+", "+maxPixelScale[1]+"] -> result["+ + resultX+", "+resultY+"], changed "+changed); + } + result[0] = resultX; + result[1] = resultY; + return changed; + } } diff --git a/src/nativewindow/classes/jogamp/nativewindow/WrappedSurface.java b/src/nativewindow/classes/jogamp/nativewindow/WrappedSurface.java index d3439b53f..cfcca7d05 100644 --- a/src/nativewindow/classes/jogamp/nativewindow/WrappedSurface.java +++ b/src/nativewindow/classes/jogamp/nativewindow/WrappedSurface.java @@ -42,7 +42,7 @@ import com.jogamp.nativewindow.UpstreamSurfaceHookMutableSize; * @see ProxySurface */ public class WrappedSurface extends ProxySurfaceImpl implements ScalableSurface { - private final int[] hasPixelScale = new int[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE }; + private final float[] hasPixelScale = new float[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE }; private long surfaceHandle; /** @@ -104,27 +104,23 @@ public class WrappedSurface extends ProxySurfaceImpl implements ScalableSurface /** * {@inheritDoc} * <p> - * {@link WrappedSurface}'s implementation uses the {@link #setSurfaceScale(int[]) given pixelScale} directly. + * {@link WrappedSurface}'s implementation uses the {@link #setSurfaceScale(float[]) given pixelScale} directly. * </p> */ @Override public final int[] convertToWindowUnits(final int[] pixelUnitsAndResult) { - pixelUnitsAndResult[0] /= hasPixelScale[0]; - pixelUnitsAndResult[1] /= hasPixelScale[1]; - return pixelUnitsAndResult; + return SurfaceScaleUtils.scaleInv(pixelUnitsAndResult, pixelUnitsAndResult, hasPixelScale); } /** * {@inheritDoc} * <p> - * {@link WrappedSurface}'s implementation uses the {@link #setSurfaceScale(int[]) given pixelScale} directly. + * {@link WrappedSurface}'s implementation uses the {@link #setSurfaceScale(float[]) given pixelScale} directly. * </p> */ @Override public final int[] convertToPixelUnits(final int[] windowUnitsAndResult) { - windowUnitsAndResult[0] *= hasPixelScale[0]; - windowUnitsAndResult[1] *= hasPixelScale[1]; - return windowUnitsAndResult; + return SurfaceScaleUtils.scale(windowUnitsAndResult, windowUnitsAndResult, hasPixelScale); } /** @@ -147,25 +143,32 @@ public class WrappedSurface extends ProxySurfaceImpl implements ScalableSurface * </p> */ @Override - public final void setSurfaceScale(final int[] pixelScale) { - hasPixelScale[0] = pixelScale[0]; - hasPixelScale[1] = pixelScale[1]; + public final boolean setSurfaceScale(final float[] pixelScale) { + final boolean changed = hasPixelScale[0] != pixelScale[0] || hasPixelScale[1] != pixelScale[1]; + System.arraycopy(pixelScale, 0, hasPixelScale, 0, 2); + return changed; } @Override - public final int[] getRequestedSurfaceScale(final int[] result) { + public final float[] getRequestedSurfaceScale(final float[] result) { System.arraycopy(hasPixelScale, 0, result, 0, 2); return result; } @Override - public final int[] getCurrentSurfaceScale(final int[] result) { + public final float[] getCurrentSurfaceScale(final float[] result) { System.arraycopy(hasPixelScale, 0, result, 0, 2); return result; } @Override - public final int[] getNativeSurfaceScale(final int[] result) { + public float[] getMinimumSurfaceScale(final float[] result) { + System.arraycopy(hasPixelScale, 0, result, 0, 2); + return result; + } + + @Override + public final float[] getMaximumSurfaceScale(final float[] result) { System.arraycopy(hasPixelScale, 0, result, 0, 2); return result; } diff --git a/src/nativewindow/classes/jogamp/nativewindow/jawt/JAWTUtil.java b/src/nativewindow/classes/jogamp/nativewindow/jawt/JAWTUtil.java index 231a89c26..4fd2b0dca 100644 --- a/src/nativewindow/classes/jogamp/nativewindow/jawt/JAWTUtil.java +++ b/src/nativewindow/classes/jogamp/nativewindow/jawt/JAWTUtil.java @@ -56,6 +56,7 @@ import javax.media.nativewindow.ToolkitLock; import jogamp.common.os.PlatformPropsImpl; import jogamp.nativewindow.Debug; import jogamp.nativewindow.NWJNILibLoader; +import jogamp.nativewindow.macosx.OSXUtil; import com.jogamp.common.os.Platform; import com.jogamp.common.util.PropertyAccess; @@ -93,6 +94,7 @@ public class JAWTUtil { private static final ToolkitLock jawtToolkitLock; private static final Method getScaleFactorMethod; + private static final Method getCGDisplayIDMethodOnOSX; private static class PrivilegedDataBlob1 { PrivilegedDataBlob1() { @@ -101,6 +103,7 @@ public class JAWTUtil { Method sunToolkitAWTLockMethod; Method sunToolkitAWTUnlockMethod; Method getScaleFactorMethod; + Method getCGDisplayIDMethodOnOSX; boolean ok; } @@ -321,6 +324,7 @@ public class JAWTUtil { hasSunToolkitAWTLock = false; // hasSunToolkitAWTLock = false; getScaleFactorMethod = null; + getCGDisplayIDMethodOnOSX = null; } else { // Non-headless case JAWTJNILibLoader.initSingleton(); // load libjawt.so @@ -357,8 +361,13 @@ public class JAWTUtil { } try { final GraphicsDevice gd = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice(); - d.getScaleFactorMethod = gd.getClass().getDeclaredMethod("getScaleFactor"); + final Class<?> gdClass = gd.getClass(); + d.getScaleFactorMethod = gdClass.getDeclaredMethod("getScaleFactor"); d.getScaleFactorMethod.setAccessible(true); + if( Platform.OSType.MACOS == PlatformPropsImpl.OS_TYPE ) { + d.getCGDisplayIDMethodOnOSX = gdClass.getDeclaredMethod("getCGDisplayID"); + d.getCGDisplayIDMethodOnOSX.setAccessible(true); + } } catch (final Throwable t) {} return d; } @@ -366,6 +375,7 @@ public class JAWTUtil { sunToolkitAWTLockMethod = pdb1.sunToolkitAWTLockMethod; sunToolkitAWTUnlockMethod = pdb1.sunToolkitAWTUnlockMethod; getScaleFactorMethod = pdb1.getScaleFactorMethod; + getCGDisplayIDMethodOnOSX = pdb1.getCGDisplayIDMethodOnOSX; boolean _hasSunToolkitAWTLock = false; if ( pdb1.ok ) { @@ -545,20 +555,46 @@ public class JAWTUtil { * Note: Currently only supported on OSX since 1.7.0_40 for HiDPI retina displays * </p> * @param device the {@link GraphicsDevice} instance used to query the pixel scale - * @return the pixel scale factor + * @param minScale current and output min scale values + * @param maxScale current and output max scale values + * @return {@code true} if the given min and max scale values have changed, otherwise {@code false}. */ - public static final int getPixelScale(final GraphicsDevice device) { + public static final boolean getPixelScale(final GraphicsDevice device, final float[] minScale, final float[] maxScale) { + // Shall we allow ]0..1[ minimum scale? + boolean changed = minScale[0] != 1f || minScale[1] != 1f; + minScale[0] = 1f; + minScale[1] = 1f; + float sx = 1f; + float sy = 1f; if( !SKIP_AWT_HIDPI ) { + if( null != getCGDisplayIDMethodOnOSX ) { + // OSX specific, preserving double type + try { + final Object res = getCGDisplayIDMethodOnOSX.invoke(device); + if (res instanceof Integer) { + final int displayID = ((Integer)res).intValue(); + sx = (float) OSXUtil.GetPixelScaleByDisplayID(displayID); + sy = sx; + } + } catch (final Throwable t) {} + } if( null != getScaleFactorMethod ) { + // Generic (?) try { final Object res = getScaleFactorMethod.invoke(device); if (res instanceof Integer) { - return ((Integer)res).intValue(); + sx = ((Integer)res).floatValue(); + } else if ( res instanceof Double) { + sx = ((Double)res).floatValue(); } + sy = sx; } catch (final Throwable t) {} } } - return 1; + changed = maxScale[0] != sx || maxScale[1] != sy; + maxScale[0] = sx; + maxScale[1] = sy; + return changed; } /** @@ -574,20 +610,23 @@ public class JAWTUtil { * Note: Currently only supported on OSX since 1.7.0_40 for HiDPI retina displays * </p> * @param gc the {@link GraphicsConfiguration} instance used to query the pixel scale - * @return the pixel scale factor + * @param minScale current and output min scale values + * @param maxScale current and output max scale values + * @return {@code true} if the given min and max scale values have changed, otherwise {@code false}. */ - public static final int getPixelScale(final GraphicsConfiguration gc) { + public static final boolean getPixelScale(final GraphicsConfiguration gc, final float[] minScale, final float[] maxScale) { final GraphicsDevice device = null != gc ? gc.getDevice() : null; - final int ps; + boolean changed; if( null == device ) { - ps = 0; + changed = minScale[0] != 1f || minScale[1] != 1f || maxScale[0] != 1f || maxScale[1] != 1f; + minScale[0] = 1f; + minScale[1] = 1f; + maxScale[0] = 1f; + maxScale[1] = 1f; } else { - ps = JAWTUtil.getPixelScale(device); - } - if( DEBUG ) { - System.err.println("JAWTUtil.updatePixelScale: Fetched "+ps); + changed = JAWTUtil.getPixelScale(device, minScale, maxScale); } - return ps; + return changed; } } diff --git a/src/nativewindow/classes/jogamp/nativewindow/jawt/macosx/MacOSXJAWTWindow.java b/src/nativewindow/classes/jogamp/nativewindow/jawt/macosx/MacOSXJAWTWindow.java index fae8db52a..1c6c41262 100644 --- a/src/nativewindow/classes/jogamp/nativewindow/jawt/macosx/MacOSXJAWTWindow.java +++ b/src/nativewindow/classes/jogamp/nativewindow/jawt/macosx/MacOSXJAWTWindow.java @@ -48,7 +48,6 @@ import java.security.PrivilegedAction; import javax.media.nativewindow.AbstractGraphicsConfiguration; import javax.media.nativewindow.Capabilities; import javax.media.nativewindow.NativeSurface; -import javax.media.nativewindow.NativeWindow; import javax.media.nativewindow.NativeWindowException; import javax.media.nativewindow.MutableSurface; import javax.media.nativewindow.util.Point; @@ -116,13 +115,10 @@ public class MacOSXJAWTWindow extends JAWTWindow implements MutableSurface { } @Override - public void setSurfaceScale(final int[] pixelScale) { + public boolean setSurfaceScale(final float[] pixelScale) { super.setSurfaceScale(pixelScale); - if( 0 != getWindowHandle() ) { // locked at least once ! - final int hadPixelScaleX = getPixelScaleX(); - updatePixelScale(); - - if( hadPixelScaleX != getPixelScaleX() && 0 != getAttachedSurfaceLayer() ) { + if( 0 != getWindowHandle() && setReqPixelScale() ) { // locked at least once _and_ updated pixel-scale + if( 0 != getAttachedSurfaceLayer() ) { OSXUtil.RunOnMainThread(false, false, new Runnable() { @Override public void run() { @@ -133,6 +129,9 @@ public class MacOSXJAWTWindow extends JAWTWindow implements MutableSurface { } }); } + return true; + } else { + return false; } } diff --git a/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java b/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java index 9af74d9f5..7cd0439b7 100644 --- a/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java +++ b/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java @@ -31,8 +31,6 @@ import javax.media.nativewindow.NativeWindowException; import javax.media.nativewindow.NativeWindowFactory; import javax.media.nativewindow.util.Insets; import javax.media.nativewindow.util.Point; -import javax.media.nativewindow.util.Rectangle; -import javax.media.nativewindow.util.RectangleImmutable; import com.jogamp.common.util.Function; import com.jogamp.common.util.FunctionTask; @@ -109,64 +107,14 @@ public class OSXUtil implements ToolkitProperties { return (Insets) GetInsets0(windowOrView); } - /** - * Returns the pixel-scale of the NSScreen, with the highest - * {@link RectangleImmutable#coverage(RectangleImmutable) coverage} of the given rectangle in window units. - * <p> - * If no coverage is detected the pixel-scale of the first NSScreen is returned. - * </p> - * @param r arbitrary rectangle in window units - * @param screenIndexOut storage returning the native screen index containing the given rectangle - */ - public static double GetPixelScale(final RectangleImmutable r, final int[] screenIndexOut) { - if( DEBUG ) { - System.err.printf("GetPixelScale covering %s%n", r.toString()); - } - final int screenCount; - final RectangleImmutable[] screenBounds; - final double[] pixelScales; - { - final double[] sd = GetScreenData0(); - if( 0 != sd.length % 5 ) { - throw new InternalError("GetScreenData0 didn't return multiple of 5 but "+sd.length); - } - screenCount = sd.length / 5; - screenBounds = new RectangleImmutable[screenCount]; - pixelScales = new double[screenCount] ; - for(int i=0; i<screenCount; i++) { - final int j = i*5; - pixelScales[i] = sd[j+0]; - screenBounds[i] = new Rectangle((int)sd[j+1], (int)sd[j+2], (int)sd[j+3], (int)sd[j+4]); - if( DEBUG ) { - System.err.printf("GetPixelScale.Screen[%d]: scale %f, bounds[%f / %f %f x %f]%n", - i, pixelScales[i], sd[j+1], sd[j+2], sd[j+3], sd[j+4]); - } - } - } - double pixelScale = pixelScales[0]; - screenIndexOut[0] = 0; - float maxCoverage = Float.MIN_VALUE; - for(int i=screenCount-1; i>=0; i--) { - final RectangleImmutable sb = screenBounds[i]; - final float coverage = sb.coverage(r); - if( coverage > maxCoverage ) { - maxCoverage = coverage; - screenIndexOut[0] = i; - pixelScale = pixelScales[i]; - } - } - if( DEBUG ) { - System.err.printf("GetPixelScale Result: screen %d, scale %f%n%n", screenIndexOut[0], pixelScale); - } - return pixelScale; - } - - public static double GetPixelScale(final int screenIndex) { + public static double GetPixelScaleByScreenIdx(final int screenIndex) { return GetPixelScale0(screenIndex); } - + public static double GetPixelScaleByDisplayID(final int displayID) { + return GetPixelScale1(displayID); + } public static double GetPixelScale(final long windowOrView) { - return GetPixelScale1(windowOrView); + return GetPixelScale2(windowOrView); } public static long CreateNSWindow(final int x, final int y, final int width, final int height) { @@ -447,9 +395,9 @@ public class OSXUtil implements ToolkitProperties { private static native boolean isNSWindow0(long object); private static native Object GetLocationOnScreen0(long windowOrView, int src_x, int src_y); private static native Object GetInsets0(long windowOrView); - private static native double[] GetScreenData0(); private static native double GetPixelScale0(int screenIndex); - private static native double GetPixelScale1(long windowOrView); + private static native double GetPixelScale1(int displayID); + private static native double GetPixelScale2(long windowOrView); private static native long CreateNSWindow0(int x, int y, int width, int height); private static native void DestroyNSWindow0(long nsWindow); private static native long GetNSView0(long nsWindow); diff --git a/src/nativewindow/native/macosx/OSXmisc.m b/src/nativewindow/native/macosx/OSXmisc.m index 997bafba0..c86025ea8 100644 --- a/src/nativewindow/native/macosx/OSXmisc.m +++ b/src/nativewindow/native/macosx/OSXmisc.m @@ -138,12 +138,24 @@ Java_jogamp_nativewindow_macosx_OSXUtil_isNSWindow0(JNIEnv *env, jclass _unused, } static CGDirectDisplayID OSXUtil_getCGDirectDisplayIDByNSScreen(NSScreen *screen) { - // Mind: typedef uint32_t CGDirectDisplayID; - however, we assume it's 64bit on 64bit ?! + // Mind: typedef uint32_t CGDirectDisplayID; NSDictionary * dict = [screen deviceDescription]; NSNumber * val = (NSNumber *) [dict objectForKey: @"NSScreenNumber"]; // [NSNumber integerValue] returns NSInteger which is 32 or 64 bit native size return (CGDirectDisplayID) [val integerValue]; } +static NSScreen * OSXUtil_getNSScreenByCGDirectDisplayID(CGDirectDisplayID displayID) { + NSArray *screens = [NSScreen screens]; + int i; + for(i=[screens count]-1; i>=0; i--) { + NSScreen * screen = (NSScreen *) [screens objectAtIndex: i]; + CGDirectDisplayID dID = OSXUtil_getCGDirectDisplayIDByNSScreen(screen); + if( dID == displayID ) { + return screen; + } + } + return (NSScreen *) [screens objectAtIndex: 0]; +} /* * Class: Java_jogamp_nativewindow_macosx_OSXUtil @@ -249,87 +261,54 @@ JNIEXPORT jobject JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_GetInsets0 return res; } -static CGDirectDisplayID GetCGDirectDisplayIDByNSScreen(NSScreen *screen) { - // Mind: typedef uint32_t CGDirectDisplayID; - however, we assume it's 64bit on 64bit ?! - NSDictionary * dict = [screen deviceDescription]; - NSNumber * val = (NSNumber *) [dict objectForKey: @"NSScreenNumber"]; - // [NSNumber integerValue] returns NSInteger which is 32 or 64 bit native size - return (CGDirectDisplayID) [val integerValue]; -} - /* * Class: Java_jogamp_nativewindow_macosx_OSXUtil - * Method: GetScreenData0 - * Signature: ()[F + * Method: GetPixelScale0 + * Signature: (I)D */ -JNIEXPORT jdoubleArray JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_GetScreenData0 - (JNIEnv *env, jclass unused) +JNIEXPORT jdouble JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_GetPixelScale0 + (JNIEnv *env, jclass unused, jint screen_idx) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; CGFloat pixelScale; - CGDirectDisplayID display; - NSRect dBounds; NSScreen *screen; NSArray *screens = [NSScreen screens]; - int sCount = [screens count]; - jdouble res[sCount*5]; - int i,j; - - for(i=0; i<sCount; i++) { - j = i*5; - screen = (NSScreen *) [screens objectAtIndex: i]; + if( screen_idx<0 || screen_idx>=[screens count] ) { + screen = NULL; + pixelScale = 1.0; + } else { + screen = (NSScreen *) [screens objectAtIndex: screen_idx]; pixelScale = 1.0; // default NS_DURING // Available >= 10.7 pixelScale = [screen backingScaleFactor]; // HiDPI scaling NS_HANDLER NS_ENDHANDLER - display = GetCGDirectDisplayIDByNSScreen(screen); - dBounds = CGDisplayBounds (display); // origin top-left - res[j+0] = (jdouble)pixelScale; - res[j+1] = (jdouble)dBounds.origin.x; - res[j+2] = (jdouble)dBounds.origin.y; - res[j+3] = (jdouble)dBounds.size.width; - res[j+4] = (jdouble)dBounds.size.height; } - - jdoubleArray jniRes = (*env)->NewDoubleArray(env, sCount*5); // x,y,w,h,scale - if (jniRes == NULL) { - NativewindowCommon_throwNewRuntimeException(env, "Could not allocate double array of size %d", sCount*5); - } - (*env)->SetDoubleArrayRegion(env, jniRes, 0, sCount*5, res); - [pool release]; - return jniRes; + return (jdouble)pixelScale; } /* * Class: Java_jogamp_nativewindow_macosx_OSXUtil - * Method: GetPixelScale0 + * Method: GetPixelScale1 * Signature: (I)D */ -JNIEXPORT jdouble JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_GetPixelScale0 - (JNIEnv *env, jclass unused, jint screen_idx) +JNIEXPORT jdouble JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_GetPixelScale1 + (JNIEnv *env, jclass unused, jint displayID) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; CGFloat pixelScale; - NSScreen *screen; - NSArray *screens = [NSScreen screens]; - if( screen_idx<0 || screen_idx>=[screens count] ) { - screen = NULL; - pixelScale = 0.0; - } else { - screen = (NSScreen *) [screens objectAtIndex: screen_idx]; - pixelScale = 1.0; // default + NSScreen *screen = OSXUtil_getNSScreenByCGDirectDisplayID((CGDirectDisplayID)displayID); + pixelScale = 1.0; // default NS_DURING - // Available >= 10.7 - pixelScale = [screen backingScaleFactor]; // HiDPI scaling + // Available >= 10.7 + pixelScale = [screen backingScaleFactor]; // HiDPI scaling NS_HANDLER NS_ENDHANDLER - } [pool release]; return (jdouble)pixelScale; @@ -340,7 +319,7 @@ NS_ENDHANDLER * Method: GetPixelScale1 * Signature: (J)D */ -JNIEXPORT jdouble JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_GetPixelScale1 +JNIEXPORT jdouble JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_GetPixelScale2 (JNIEnv *env, jclass unused, jlong winOrView) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; diff --git a/src/newt/classes/com/jogamp/newt/MonitorDevice.java b/src/newt/classes/com/jogamp/newt/MonitorDevice.java index 126162006..1a3222c71 100644 --- a/src/newt/classes/com/jogamp/newt/MonitorDevice.java +++ b/src/newt/classes/com/jogamp/newt/MonitorDevice.java @@ -30,6 +30,7 @@ package com.jogamp.newt; import java.util.List; +import javax.media.nativewindow.ScalableSurface; import javax.media.nativewindow.util.DimensionImmutable; import javax.media.nativewindow.util.Rectangle; import javax.media.nativewindow.util.RectangleImmutable; @@ -51,6 +52,7 @@ import com.jogamp.common.util.ArrayHashSet; * <ul> * <li>{@link MonitorMode} current mode</li> * <li>{@link RectangleImmutable} viewport (rotated)</li> + * <li>pixel-scale (rotated)</li> * </ul></li> * </ul> * <p> @@ -65,16 +67,31 @@ public abstract class MonitorDevice { protected final ArrayHashSet<MonitorMode> supportedModes; // FIXME: May need to support mutable mode, i.e. adding modes on the fly! protected MonitorMode currentMode; protected boolean modeChanged; - protected Rectangle viewportPU; // in pixel units - protected Rectangle viewportWU; // in window units + protected final float[] pixelScale; + protected final Rectangle viewportPU; // in pixel units + protected final Rectangle viewportWU; // in window units - protected MonitorDevice(final Screen screen, final int nativeId, final DimensionImmutable sizeMM, final Rectangle viewportPU, final Rectangle viewportWU, final MonitorMode currentMode, final ArrayHashSet<MonitorMode> supportedModes) { + /** + * @param screen associated {@link Screen} + * @param nativeId unique monitor device ID + * @param sizeMM size in millimeters + * @param currentMode + * @param pixelScale pre-fetched current pixel-scale, maybe {@code null} for {@link ScalableSurface#IDENTITY_PIXELSCALE}. + * @param viewportPU viewport in pixel-units + * @param viewportWU viewport in window-units + * @param supportedModes all supported {@link MonitorMode}s + */ + protected MonitorDevice(final Screen screen, final int nativeId, final DimensionImmutable sizeMM, + final MonitorMode currentMode, + final float[] pixelScale, final Rectangle viewportPU, final Rectangle viewportWU, + final ArrayHashSet<MonitorMode> supportedModes) { this.screen = screen; this.nativeId = nativeId; this.sizeMM = sizeMM; this.originalMode = currentMode; this.supportedModes = supportedModes; this.currentMode = currentMode; + this.pixelScale = null != pixelScale ? pixelScale : new float[] { 1.0f, 1.0f }; this.viewportPU = viewportPU; this.viewportWU = viewportWU; this.modeChanged = false; @@ -180,26 +197,40 @@ public abstract class MonitorDevice { } /** - * Returns the {@link RectangleImmutable rectangular} portion + * Returns the current {@link RectangleImmutable rectangular} portion * of the <b>rotated</b> virtual {@link Screen} size in pixel units * represented by this monitor, i.e. top-left origin and size. - * @see Screen + * @see #getPixelScale() + * @see Screen#getViewport() */ public final RectangleImmutable getViewport() { return viewportPU; } /** - * Returns the {@link RectangleImmutable rectangular} portion + * Returns the current {@link RectangleImmutable rectangular} portion * of the <b>rotated</b> virtual {@link Screen} size in window units * represented by this monitor, i.e. top-left origin and size. - * @see Screen + * @see #getPixelScale() + * @see Screen#getViewportInWindowUnits() */ public final RectangleImmutable getViewportInWindowUnits() { return viewportWU; } /** + * Returns the current <b>rotated</b> pixel-scale + * of this monitor, i.e. horizontal and vertical. + * @see #getViewportInWindowUnits() + * @see #getViewport() + * @see ScalableSurface#getMaximumSurfaceScale(float[]) + */ + public float[] getPixelScale(final float[] result) { + System.arraycopy(pixelScale, 0, result, 0, 2); + return result; + } + + /** * Returns <code>true</code> if given screen coordinates in pixel units * are contained by this {@link #getViewport() viewport}, otherwise <code>false</code>. * @param x x-coord in pixel units @@ -292,7 +323,8 @@ public abstract class MonitorDevice { @Override public String toString() { - return "Monitor[Id "+Display.toHexString(nativeId)+", "+sizeMM+" mm, viewport "+viewportPU+ " [pixels], "+viewportWU+" [window], orig "+originalMode+", curr "+currentMode+ + return "Monitor[Id "+Display.toHexString(nativeId)+", "+sizeMM+" mm, pixelScale ["+pixelScale[0]+", "+pixelScale[1]+ + "], viewport "+viewportPU+ " [pixels], "+viewportWU+" [window], orig "+originalMode+", curr "+currentMode+ ", modeChanged "+modeChanged+", modeCount "+supportedModes.size()+"]"; } } diff --git a/src/newt/classes/com/jogamp/newt/Window.java b/src/newt/classes/com/jogamp/newt/Window.java index c4ca9a554..7b7937c98 100644 --- a/src/newt/classes/com/jogamp/newt/Window.java +++ b/src/newt/classes/com/jogamp/newt/Window.java @@ -273,7 +273,7 @@ public interface Window extends NativeWindow, WindowClosingProtocol, ScalableSur * 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} + * Method takes the {@link #getCurrentSurfaceScale(float[]) current surface-scale} and {@link #getMaximumSurfaceScale(float[]) native surface-scale} * into account, i.e.: * <pre> * surfacePpMM = monitorPpMM * currentSurfaceScale / nativeSurfaceScale, diff --git a/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java b/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java index e890bc640..b469492c8 100644 --- a/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java +++ b/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java @@ -474,6 +474,13 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto } jawtWindow = NewtFactoryAWT.getNativeWindow(NewtCanvasAWT.this, null != newtChild ? newtChild.getRequestedCapabilities() : null); jawtWindow.setShallUseOffscreenLayer(shallUseOffscreenLayer); + // enforce initial lock on AWT-EDT, allowing acquisition of pixel-scale + jawtWindow.lockSurface(); + try { + // attachNewtChild sets surface scale! + } finally { + jawtWindow.unlockSurface(); + } awtWindowClosingProtocol.addClosingListener(); componentAdded = true; // Bug 910 if(DEBUG) { @@ -486,6 +493,25 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto } } } + private final boolean updatePixelScale() { + if( jawtWindow.updatePixelScale(true) ) { + final Window cWin = newtChild; + final Window dWin = cWin.getDelegatedWindow(); + if( dWin instanceof WindowImpl ) { + final float[] maxPixelScale = jawtWindow.getMaximumSurfaceScale(new float[2]); + final float[] minPixelScale = jawtWindow.getMinimumSurfaceScale(new float[2]); + ((WindowImpl)dWin).pixelScaleChangeNotify(minPixelScale, maxPixelScale, true); + // ((WindowImpl)dWin).sizeChangedNotify(true /* defer */, getWidth(), getHeight(), true /* force */); + } else { + final float[] reqPixelScale = jawtWindow.getRequestedSurfaceScale(new float[2]); + if( jawtWindow.setSurfaceScale(reqPixelScale) ) { + // jawtWindow.getRequestedSurfaceScale(reqPixelScale); + } + } + return true; + } + return false; + } @Override public void removeNotify() { @@ -588,7 +614,11 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto System.err.println("NewtCanvasAWT.reshape: "+x+"/"+y+" "+width+"x"+height); } if( validateComponent(true) ) { - // newtChild.setSize(width, height); + if( !printActive && updatePixelScale() ) { + // NOP + } else { + // newtChild.setSize(width, height); + } } } } @@ -877,18 +907,12 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto } final int w = getWidth(); final int h = getHeight(); - final boolean isNValid = newtChild.isNativeValid(); if(DEBUG) { - System.err.println("NewtCanvasAWT.attachNewtChild.2: size "+w+"x"+h+", isNValid "+isNValid); + System.err.println("NewtCanvasAWT.attachNewtChild.2: size "+w+"x"+h+", isNValid "+newtChild.isNativeValid()); } newtChild.setVisible(false); newtChild.setSize(w, h); - final int[] reqSurfaceScale = new int[2]; - if( isNValid ) { - newtChild.getCurrentSurfaceScale(reqSurfaceScale); - } else { - newtChild.getRequestedSurfaceScale(reqSurfaceScale); - } + final float[] reqSurfaceScale = newtChild.getRequestedSurfaceScale(new float[2]); jawtWindow.setSurfaceScale(reqSurfaceScale); newtChild.reparentWindow(jawtWindow, -1, -1, Window.REPARENT_HINT_BECOMES_VISIBLE); newtChild.addSurfaceUpdatedListener(jawtWindow); diff --git a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java index 2ba030f76..0d286f25a 100644 --- a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java +++ b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java @@ -401,23 +401,28 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind } @Override - public final void setSurfaceScale(final int[] pixelScale) { - window.setSurfaceScale(pixelScale); + public final boolean setSurfaceScale(final float[] pixelScale) { + return window.setSurfaceScale(pixelScale); } @Override - public final int[] getRequestedSurfaceScale(final int[] result) { + public final float[] getRequestedSurfaceScale(final float[] result) { return window.getRequestedSurfaceScale(result); } @Override - public final int[] getCurrentSurfaceScale(final int[] result) { + public final float[] getCurrentSurfaceScale(final float[] result) { return window.getCurrentSurfaceScale(result); } @Override - public final int[] getNativeSurfaceScale(final int[] result) { - return window.getNativeSurfaceScale(result); + public final float[] getMinimumSurfaceScale(final float[] result) { + return window.getMinimumSurfaceScale(result); + } + + @Override + public final float[] getMaximumSurfaceScale(final float[] result) { + return window.getMaximumSurfaceScale(result); } @Override diff --git a/src/newt/classes/jogamp/newt/MonitorDeviceImpl.java b/src/newt/classes/jogamp/newt/MonitorDeviceImpl.java index 72300740f..f1bd445ab 100644 --- a/src/newt/classes/jogamp/newt/MonitorDeviceImpl.java +++ b/src/newt/classes/jogamp/newt/MonitorDeviceImpl.java @@ -28,6 +28,7 @@ package jogamp.newt; +import javax.media.nativewindow.ScalableSurface; import javax.media.nativewindow.util.DimensionImmutable; import javax.media.nativewindow.util.Rectangle; @@ -38,8 +39,21 @@ import com.jogamp.newt.Screen; public class MonitorDeviceImpl extends MonitorDevice { - public MonitorDeviceImpl(final ScreenImpl screen, final int nativeId, final DimensionImmutable sizeMM, final Rectangle viewportPU, final Rectangle viewportWU, final MonitorMode currentMode, final ArrayHashSet<MonitorMode> supportedModes) { - super(screen, nativeId, sizeMM, viewportPU, viewportWU, currentMode, supportedModes); + /** + * @param screen associated {@link Screen} + * @param nativeId unique monitor device ID + * @param sizeMM size in millimeters + * @param currentMode + * @param pixelScale pre-fetched current pixel-scale, maybe {@code null} for {@link ScalableSurface#IDENTITY_PIXELSCALE}. + * @param viewportPU viewport in pixel-units + * @param viewportWU viewport in window-units + * @param supportedModes all supported {@link MonitorMode}s + */ + public MonitorDeviceImpl(final ScreenImpl screen, final int nativeId, final DimensionImmutable sizeMM, + final MonitorMode currentMode, + final float[] pixelScale, final Rectangle viewportPU, final Rectangle viewportWU, + final ArrayHashSet<MonitorMode> supportedModes) { + super(screen, nativeId, sizeMM, currentMode, pixelScale, viewportPU, viewportWU, supportedModes); } @Override diff --git a/src/newt/classes/jogamp/newt/MonitorModeProps.java b/src/newt/classes/jogamp/newt/MonitorModeProps.java index 6e376ce48..6ed3b2382 100644 --- a/src/newt/classes/jogamp/newt/MonitorModeProps.java +++ b/src/newt/classes/jogamp/newt/MonitorModeProps.java @@ -33,6 +33,7 @@ import com.jogamp.newt.MonitorDevice; import com.jogamp.newt.MonitorMode; import java.util.List; +import javax.media.nativewindow.ScalableSurface; import javax.media.nativewindow.util.Dimension; import javax.media.nativewindow.util.DimensionImmutable; import javax.media.nativewindow.util.Rectangle; @@ -256,14 +257,19 @@ public class MonitorModeProps { * <p> * Note: This variant only works for impl. w/ a unique mode key pair <i>modeId, rotation</i>. * </p> - * @param mode_idx if not null, returns the index of resulting {@link MonitorDevice} within {@link Cache#monitorDevices}. * @param cache hash arrays of unique {@link MonitorMode} components and {@link MonitorDevice}s, allowing to avoid duplicates - * @param modeProperties the input data + * @param screen the associated {@link ScreenImpl} + * @param pixelScale pre-fetched current pixel-scale, maybe {@code null} for {@link ScalableSurface#IDENTITY_PIXELSCALE}. + * @param monitorProperties the input data minus supported modes! * @param offset the offset to the input data + * @param monitor_idx if not null, returns the index of resulting {@link MonitorDevice} within {@link Cache#monitorDevices}. * @return {@link MonitorDevice} of the identical (old or new) element in {@link Cache#monitorDevices}, * matching the input <code>modeProperties</code>, or null if input could not be processed. */ - public static MonitorDevice streamInMonitorDevice(final int[] monitor_idx, final Cache cache, final ScreenImpl screen, final int[] monitorProperties, int offset) { + public static MonitorDevice streamInMonitorDevice(final Cache cache, final ScreenImpl screen, + final float[] pixelScale, + final int[] monitorProperties, int offset, + final int[] monitor_idx) { // min 11: count, id, ScreenSizeMM[width, height], Viewport[x, y, width, height], currentMonitorModeId, rotation, supportedModeId+ final int count = monitorProperties[offset]; if(MIN_MONITOR_DEVICE_PROPERTIES > count) { @@ -298,7 +304,7 @@ public class MonitorModeProps { } } } - MonitorDevice monitorDevice = new MonitorDeviceImpl(screen, id, sizeMM, viewportPU, viewportWU, currentMode, supportedModes); + MonitorDevice monitorDevice = new MonitorDeviceImpl(screen, id, sizeMM, currentMode, pixelScale, viewportPU, viewportWU, supportedModes); if(null!=cache) { monitorDevice = cache.monitorDevices.getOrAdd(monitorDevice); } @@ -329,17 +335,23 @@ public class MonitorModeProps { * This variant expects <code>count</code> to be <code>{@link MIN_MONITOR_DEVICE_PROPERTIES} - 1 - {@link NUM_MONITOR_MODE_PROPERTIES}</code>, * due to lack of supported mode and current mode. * </p> - * - * @param mode_idx if not null, returns the index of resulting {@link MonitorDevice} within {@link Cache#monitorDevices}. * @param cache hash arrays of unique {@link MonitorMode} components and {@link MonitorDevice}s, allowing to avoid duplicates - * @param supportedModes pre-assembled list of supported {@link MonitorMode}s from cache. + * @param screen the associated {@link ScreenImpl} * @param currentMode pre-fetched current {@link MonitorMode}s from cache. - * @param modeProperties the input data minus supported modes! + * @param pixelScale pre-fetched current pixel-scale, maybe {@code null} for {@link ScalableSurface#IDENTITY_PIXELSCALE}. + * @param supportedModes pre-assembled list of supported {@link MonitorMode}s from cache. + * @param monitorProperties the input data minus supported modes! * @param offset the offset to the input data + * @param monitor_idx if not null, returns the index of resulting {@link MonitorDevice} within {@link Cache#monitorDevices}. * @return {@link MonitorDevice} of the identical (old or new) element in {@link Cache#monitorDevices}, * matching the input <code>modeProperties</code>, or null if input could not be processed. */ - public static MonitorDevice streamInMonitorDevice(final int[] monitor_idx, final Cache cache, final ScreenImpl screen, final ArrayHashSet<MonitorMode> supportedModes, final MonitorMode currentMode, final int[] monitorProperties, int offset) { + public static MonitorDevice streamInMonitorDevice(final Cache cache, final ScreenImpl screen, + final MonitorMode currentMode, + final float[] pixelScale, + final ArrayHashSet<MonitorMode> supportedModes, + final int[] monitorProperties, int offset, + final int[] monitor_idx) { // min 11: count, id, ScreenSizeMM[width, height], Viewport[x, y, width, height], currentMonitorModeId, rotation, supportedModeId+ final int count = monitorProperties[offset]; if(MIN_MONITOR_DEVICE_PROPERTIES - 1 - NUM_MONITOR_MODE_PROPERTIES != count) { @@ -356,7 +368,7 @@ public class MonitorModeProps { final DimensionImmutable sizeMM = streamInResolution(monitorProperties, offset); offset+=NUM_RESOLUTION_PROPERTIES; final Rectangle viewportPU = new Rectangle(monitorProperties[offset++], monitorProperties[offset++], monitorProperties[offset++], monitorProperties[offset++]); final Rectangle viewportWU = new Rectangle(monitorProperties[offset++], monitorProperties[offset++], monitorProperties[offset++], monitorProperties[offset++]); - MonitorDevice monitorDevice = new MonitorDeviceImpl(screen, id, sizeMM, viewportPU, viewportWU, currentMode, supportedModes); + MonitorDevice monitorDevice = new MonitorDeviceImpl(screen, id, sizeMM, currentMode, pixelScale, viewportPU, viewportWU, supportedModes); if(null!=cache) { monitorDevice = cache.monitorDevices.getOrAdd(monitorDevice); } diff --git a/src/newt/classes/jogamp/newt/ScreenImpl.java b/src/newt/classes/jogamp/newt/ScreenImpl.java index e73e153ad..c57f84528 100644 --- a/src/newt/classes/jogamp/newt/ScreenImpl.java +++ b/src/newt/classes/jogamp/newt/ScreenImpl.java @@ -364,8 +364,8 @@ public abstract class ScreenImpl extends Screen implements MonitorModeListener { * <li>{@link MonitorModeProps#MIN_MONITOR_DEVICE_PROPERTIES}</li> * </ul>, i.e. * <ul> - * <li>{@link MonitorModeProps#streamInMonitorDevice(int[], jogamp.newt.MonitorModeProps.Cache, ScreenImpl, int[], int)}</li> - * <li>{@link MonitorModeProps#streamInMonitorDevice(int[], jogamp.newt.MonitorModeProps.Cache, ScreenImpl, ArrayHashSet, int[], int)}</li> + * <li>{@link MonitorModeProps#streamInMonitorDevice(jogamp.newt.MonitorModeProps.Cache, ScreenImpl, double[], int[], int, int[])}</li> + * <li>{@link MonitorModeProps#streamInMonitorDevice(int[], jogamp.newt.MonitorModeProps.Cache, ArrayHashSet, int[], int, ScreenImpl)}</li> * <li>{@link MonitorModeProps#streamInMonitorMode(int[], jogamp.newt.MonitorModeProps.Cache, int[], int)}</li> * </ul> * @param cache memory pool caching the result @@ -373,6 +373,7 @@ public abstract class ScreenImpl extends Screen implements MonitorModeListener { protected abstract void collectNativeMonitorModesAndDevicesImpl(MonitorModeProps.Cache cache); protected boolean updateNativeMonitorDeviceViewportImpl(final MonitorDevice monitor, + final float[] pixelScale, final Rectangle viewportPU, final Rectangle viewportWU) { return false; } @@ -428,9 +429,14 @@ public abstract class ScreenImpl extends Screen implements MonitorModeListener { final List<MonitorDevice> monitors = getMonitorDevices(); for(int i=monitors.size()-1; i>=0; i--) { final MonitorDeviceImpl monitor = (MonitorDeviceImpl) monitors.get(i); - final boolean viewportUpdated = updateNativeMonitorDeviceViewportImpl(monitor, monitor.getMutuableViewportPU(), monitor.getMutuableViewportWU()); + final float[] pixelScale = monitor.getPixelScale(new float[2]); + final boolean viewportUpdated = updateNativeMonitorDeviceViewportImpl(monitor, pixelScale, + monitor.getMutuableViewportPU(), + monitor.getMutuableViewportWU()); if( DEBUG ) { - System.err.println("Screen.updateMonitorViewport["+i+"] @ "+Thread.currentThread().getName()+": updated: "+viewportUpdated+", PU "+monitor.getViewport()+", WU "+monitor.getViewportInWindowUnits()); + System.err.println("Screen.updateMonitorViewport["+i+"] @ "+Thread.currentThread().getName()+": updated: "+viewportUpdated+ + ", PU "+monitor.getViewport()+", WU "+monitor.getViewportInWindowUnits()+ + ", pixelScale ["+pixelScale[0]+", "+pixelScale[1]+"]"); } } } @@ -510,7 +516,7 @@ public abstract class ScreenImpl extends Screen implements MonitorModeListener { if( MonitorModeProps.MIN_MONITOR_DEVICE_PROPERTIES != i ) { throw new InternalError("XX"); } - return MonitorModeProps.streamInMonitorDevice(null, cache, this, props, 0); + return MonitorModeProps.streamInMonitorDevice(cache, this, null, props, 0, null); } /** diff --git a/src/newt/classes/jogamp/newt/WindowImpl.java b/src/newt/classes/jogamp/newt/WindowImpl.java index 0c4dcd192..2230acd67 100644 --- a/src/newt/classes/jogamp/newt/WindowImpl.java +++ b/src/newt/classes/jogamp/newt/WindowImpl.java @@ -154,9 +154,10 @@ 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 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 }; + protected final float[] minPixelScale = new float[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE }; + protected final float[] maxPixelScale = new float[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE }; + protected final float[] hasPixelScale = new float[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE }; + protected final float[] reqPixelScale = new float[] { 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) @@ -1087,8 +1088,8 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer } @Override public final void setSurfaceSize(final int pixelWidth, final int pixelHeight) { - // FIXME HiDPI: Shortcut, may need to adjust if we change scaling methodology - setSize(pixelWidth / getPixelScaleX(), pixelHeight / getPixelScaleY()); + setSize( SurfaceScaleUtils.scaleInv(pixelWidth, getPixelScaleX()), + SurfaceScaleUtils.scaleInv(pixelHeight, getPixelScaleY()) ); } @Override public final void setTopLevelSize(final int width, final int height) { @@ -1181,8 +1182,10 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer parentWindowHandle = 0; hasPixelScale[0] = ScalableSurface.IDENTITY_PIXELSCALE; hasPixelScale[1] = ScalableSurface.IDENTITY_PIXELSCALE; - nativePixelScale[0] = ScalableSurface.IDENTITY_PIXELSCALE; - nativePixelScale[1] = ScalableSurface.IDENTITY_PIXELSCALE; + minPixelScale[0] = ScalableSurface.IDENTITY_PIXELSCALE; + minPixelScale[1] = ScalableSurface.IDENTITY_PIXELSCALE; + maxPixelScale[0] = ScalableSurface.IDENTITY_PIXELSCALE; + maxPixelScale[1] = ScalableSurface.IDENTITY_PIXELSCALE; _lock.unlock(); } @@ -1926,16 +1929,12 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer @Override public final int[] convertToWindowUnits(final int[] pixelUnitsAndResult) { - pixelUnitsAndResult[0] /= getPixelScaleX(); - pixelUnitsAndResult[1] /= getPixelScaleY(); - return pixelUnitsAndResult; + return SurfaceScaleUtils.scaleInv(pixelUnitsAndResult, pixelUnitsAndResult, hasPixelScale); } @Override public final int[] convertToPixelUnits(final int[] windowUnitsAndResult) { - windowUnitsAndResult[0] *= getPixelScaleX(); - windowUnitsAndResult[1] *= getPixelScaleY(); - return windowUnitsAndResult; + return SurfaceScaleUtils.scale(windowUnitsAndResult, windowUnitsAndResult, hasPixelScale); } protected final Point convertToWindowUnits(final Point pixelUnitsAndResult) { @@ -1947,43 +1946,50 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer } /** HiDPI: We currently base scaling of window units to pixel units on an integer scale factor per component. */ - protected final int getPixelScaleX() { + protected final float getPixelScaleX() { return hasPixelScale[0]; } /** HiDPI: We currently base scaling of window units to pixel units on an integer scale factor per component. */ - protected final int getPixelScaleY() { + protected final float getPixelScaleY() { return hasPixelScale[1]; } @Override - public void setSurfaceScale(final int[] pixelScale) { - SurfaceScaleUtils.validateReqPixelScale(reqPixelScale, pixelScale, DEBUG_IMPLEMENTATION ? getClass().getSimpleName() : null); + public boolean setSurfaceScale(final float[] pixelScale) { + System.arraycopy(pixelScale, 0, reqPixelScale, 0, 2); + return false; } @Override - public final int[] getRequestedSurfaceScale(final int[] result) { + public final float[] getRequestedSurfaceScale(final float[] result) { System.arraycopy(reqPixelScale, 0, result, 0, 2); return result; } @Override - public final int[] getCurrentSurfaceScale(final int[] result) { + public final float[] getCurrentSurfaceScale(final float[] result) { System.arraycopy(hasPixelScale, 0, result, 0, 2); return result; } @Override - public final int[] getNativeSurfaceScale(final int[] result) { - System.arraycopy(nativePixelScale, 0, result, 0, 2); + public final float[] getMinimumSurfaceScale(final float[] result) { + System.arraycopy(minPixelScale, 0, result, 0, 2); + return result; + } + + @Override + public final float[] getMaximumSurfaceScale(final float[] result) { + System.arraycopy(maxPixelScale, 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]; + ppmmStore[0] *= hasPixelScale[0] / maxPixelScale[0]; + ppmmStore[1] *= hasPixelScale[1] / maxPixelScale[1]; return ppmmStore; } @@ -2004,8 +2010,9 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer * and {@link #pixWidth} and {@link #pixHeight} in pixel units according to {@link #convertToPixelUnits(int[])}. */ protected final void defineSize(final int winWidth, final int winHeight) { - final int pixWidth = winWidth * getPixelScaleX(); // FIXME HiDPI: Shortcut, may need to adjust if we change scaling methodology - final int pixHeight = winHeight * getPixelScaleY(); + final int pixWidth = SurfaceScaleUtils.scale(winWidth, getPixelScaleX()); // FIXME HiDPI: Shortcut, may need to adjust if we change scaling methodology + final int pixHeight = SurfaceScaleUtils.scale(winHeight, getPixelScaleY()); + if(DEBUG_IMPLEMENTATION) { System.err.println("defineSize: win["+this.winWidth+"x"+this.winHeight+" -> "+winWidth+"x"+winHeight+ "], pixel["+this.pixWidth+"x"+this.pixHeight+" -> "+pixWidth+"x"+pixHeight+"]"); @@ -2631,13 +2638,13 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer // special repaint treatment case WindowEvent.EVENT_WINDOW_REPAINT: // queue repaint event in case window is locked, ie in operation - if( null != windowLock.getOwner() ) { + if( windowLock.isLockedByOtherThread() ) { // make sure only one repaint event is queued if(!repaintQueued) { repaintQueued=true; final boolean discardTO = QUEUED_EVENT_TO <= System.currentTimeMillis()-e.getWhen(); if(DEBUG_IMPLEMENTATION) { - System.err.println("Window.consumeEvent: REPAINT "+Thread.currentThread().getName()+" - queued "+e+", discard-to "+discardTO); + System.err.println("Window.consumeEvent: REPAINT [me "+Thread.currentThread().getName()+", owner "+windowLock.getOwner()+"] - queued "+e+", discard-to "+discardTO); // ExceptionUtils.dumpStackTrace(System.err); } return discardTO; // discardTO:=true -> consumed @@ -2650,10 +2657,10 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer // common treatment case WindowEvent.EVENT_WINDOW_RESIZED: // queue event in case window is locked, ie in operation - if( null != windowLock.getOwner() ) { + if( windowLock.isLockedByOtherThread() ) { final boolean discardTO = QUEUED_EVENT_TO <= System.currentTimeMillis()-e.getWhen(); if(DEBUG_IMPLEMENTATION) { - System.err.println("Window.consumeEvent: RESIZED "+Thread.currentThread().getName()+" - queued "+e+", discard-to "+discardTO); + System.err.println("Window.consumeEvent: RESIZED [me "+Thread.currentThread().getName()+", owner "+windowLock.getOwner()+"] - queued "+e+", discard-to "+discardTO); // ExceptionUtils.dumpStackTrace(System.err); } return discardTO; // discardTO:=true -> consumed @@ -3756,6 +3763,21 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer } } + /** + * Notify to update the pixel-scale values. + * @param minPixelScale + * @param maxPixelScale + * @param reset if {@code true} {@link #setSurfaceScale(float[]) reset pixel-scale} w/ {@link #getRequestedSurfaceScale(float[]) requested values} + * value to reflect the new minimum and maximum values. + */ + public final void pixelScaleChangeNotify(final float[] minPixelScale, final float[] maxPixelScale, final boolean reset) { + System.arraycopy(minPixelScale, 0, this.minPixelScale, 0, 2); + System.arraycopy(maxPixelScale, 0, this.maxPixelScale, 0, 2); + if( reset ) { + setSurfaceScale(reqPixelScale); + } + } + /** Triggered by implementation's WM events to update the client-area size in window units w/o insets/decorations. */ protected void sizeChanged(final boolean defer, final int newWidth, final int newHeight, final boolean force) { if(force || getWidth() != newWidth || getHeight() != newHeight) { diff --git a/src/newt/classes/jogamp/newt/driver/android/ScreenDriver.java b/src/newt/classes/jogamp/newt/driver/android/ScreenDriver.java index b28cdcbed..59688cd8d 100644 --- a/src/newt/classes/jogamp/newt/driver/android/ScreenDriver.java +++ b/src/newt/classes/jogamp/newt/driver/android/ScreenDriver.java @@ -113,7 +113,7 @@ public class ScreenDriver extends jogamp.newt.ScreenImpl { props[i++] = 0; // rotated viewport y window-units props[i++] = outMetrics.widthPixels; // rotated viewport width window-units props[i++] = outMetrics.heightPixels; // rotated viewport height window-units - MonitorModeProps.streamInMonitorDevice(null, cache, this, cache.monitorModes, currentMode, props, 0); + MonitorModeProps.streamInMonitorDevice(cache, this, currentMode, null, cache.monitorModes, props, 0, null); } @Override diff --git a/src/newt/classes/jogamp/newt/driver/awt/AWTCanvas.java b/src/newt/classes/jogamp/newt/driver/awt/AWTCanvas.java index eccdd63cf..76ae26764 100644 --- a/src/newt/classes/jogamp/newt/driver/awt/AWTCanvas.java +++ b/src/newt/classes/jogamp/newt/driver/awt/AWTCanvas.java @@ -69,8 +69,8 @@ public class AWTCanvas extends Canvas { private final UpstreamScalable upstreamScale; public static interface UpstreamScalable { - int[] getReqPixelScale(); - void setHasPixelScale(final int[] pixelScale); + float[] getReqPixelScale(); + void setHasPixelScale(final float[] pixelScale); } private boolean displayConfigChanged=false; @@ -148,7 +148,7 @@ public class AWTCanvas extends Canvas { // trigger initialization cycle jawtWindow.setSurfaceScale(upstreamScale.getReqPixelScale() ); jawtWindow.lockSurface(); - upstreamScale.setHasPixelScale(jawtWindow.getCurrentSurfaceScale(new int[2])); + upstreamScale.setHasPixelScale(jawtWindow.getCurrentSurfaceScale(new float[2])); jawtWindow.unlockSurface(); } diff --git a/src/newt/classes/jogamp/newt/driver/awt/ScreenDriver.java b/src/newt/classes/jogamp/newt/driver/awt/ScreenDriver.java index 57948cfc3..eb92e0d13 100644 --- a/src/newt/classes/jogamp/newt/driver/awt/ScreenDriver.java +++ b/src/newt/classes/jogamp/newt/driver/awt/ScreenDriver.java @@ -119,7 +119,7 @@ public class ScreenDriver extends ScreenImpl { props[i++] = 0; // rotated viewport y window-units props[i++] = currentMode.getRotatedWidth(); // rotated viewport width window-units props[i++] = currentMode.getRotatedHeight(); // rotated viewport height window-units - MonitorModeProps.streamInMonitorDevice(null, cache, this, cache.monitorModes, currentMode, props, 0); + MonitorModeProps.streamInMonitorDevice(cache, this, currentMode, null, cache.monitorModes, props, 0, null); } @Override diff --git a/src/newt/classes/jogamp/newt/driver/awt/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/awt/WindowDriver.java index 06dcb8ff5..2ccc8d763 100644 --- a/src/newt/classes/jogamp/newt/driver/awt/WindowDriver.java +++ b/src/newt/classes/jogamp/newt/driver/awt/WindowDriver.java @@ -100,12 +100,12 @@ public class WindowDriver extends WindowImpl { private final AWTCanvas.UpstreamScalable upstreamScalable = new AWTCanvas.UpstreamScalable() { @Override - public int[] getReqPixelScale() { + public float[] getReqPixelScale() { return WindowDriver.this.reqPixelScale; } @Override - public void setHasPixelScale(final int[] pixelScale) { + public void setHasPixelScale(final float[] pixelScale) { System.arraycopy(pixelScale, 0, WindowDriver.this.hasPixelScale, 0, 2); } }; diff --git a/src/newt/classes/jogamp/newt/driver/bcm/egl/ScreenDriver.java b/src/newt/classes/jogamp/newt/driver/bcm/egl/ScreenDriver.java index 2cd47313a..f3ac3e851 100644 --- a/src/newt/classes/jogamp/newt/driver/bcm/egl/ScreenDriver.java +++ b/src/newt/classes/jogamp/newt/driver/bcm/egl/ScreenDriver.java @@ -94,7 +94,7 @@ public class ScreenDriver extends jogamp.newt.ScreenImpl { props[i++] = 0; // rotated viewport y window-units props[i++] = fixedWidth; // FIXME rotated viewport width window-units props[i++] = fixedHeight; // FIXME rotated viewport height window-units - MonitorModeProps.streamInMonitorDevice(null, cache, this, cache.monitorModes, currentMode, props, 0); + MonitorModeProps.streamInMonitorDevice(cache, this, currentMode, null, cache.monitorModes, props, 0, null); } @Override diff --git a/src/newt/classes/jogamp/newt/driver/bcm/vc/iv/ScreenDriver.java b/src/newt/classes/jogamp/newt/driver/bcm/vc/iv/ScreenDriver.java index 64cae75f6..bc1c19fe4 100644 --- a/src/newt/classes/jogamp/newt/driver/bcm/vc/iv/ScreenDriver.java +++ b/src/newt/classes/jogamp/newt/driver/bcm/vc/iv/ScreenDriver.java @@ -87,7 +87,7 @@ public class ScreenDriver extends ScreenImpl { props[i++] = 0; // rotated viewport y window-units props[i++] = cachedWidth; // rotated viewport width window-units props[i++] = cachedWidth; // rotated viewport height window-units - MonitorModeProps.streamInMonitorDevice(null, cache, this, cache.monitorModes, currentMode, props, 0); + MonitorModeProps.streamInMonitorDevice(cache, this, currentMode, null, cache.monitorModes, props, 0, null); } @Override diff --git a/src/newt/classes/jogamp/newt/driver/intel/gdl/ScreenDriver.java b/src/newt/classes/jogamp/newt/driver/intel/gdl/ScreenDriver.java index 2ce835c52..36a95dca4 100644 --- a/src/newt/classes/jogamp/newt/driver/intel/gdl/ScreenDriver.java +++ b/src/newt/classes/jogamp/newt/driver/intel/gdl/ScreenDriver.java @@ -96,7 +96,7 @@ public class ScreenDriver extends jogamp.newt.ScreenImpl { props[i++] = 0; // rotated viewport y window-units props[i++] = cachedWidth; // rotated viewport width window-units props[i++] = cachedWidth; // rotated viewport height window-units - MonitorModeProps.streamInMonitorDevice(null, cache, this, cache.monitorModes, currentMode, props, 0); + MonitorModeProps.streamInMonitorDevice(cache, this, currentMode, null, cache.monitorModes, props, 0, null); } @Override diff --git a/src/newt/classes/jogamp/newt/driver/kd/ScreenDriver.java b/src/newt/classes/jogamp/newt/driver/kd/ScreenDriver.java index d4113561a..42659b14e 100644 --- a/src/newt/classes/jogamp/newt/driver/kd/ScreenDriver.java +++ b/src/newt/classes/jogamp/newt/driver/kd/ScreenDriver.java @@ -92,7 +92,7 @@ public class ScreenDriver extends ScreenImpl { props[i++] = 0; // rotated viewport y window-units props[i++] = cachedWidth; // rotated viewport width window-units props[i++] = cachedWidth; // rotated viewport height window-units - MonitorModeProps.streamInMonitorDevice(null, cache, this, cache.monitorModes, currentMode, props, 0); + MonitorModeProps.streamInMonitorDevice(cache, this, currentMode, null, cache.monitorModes, props, 0, null); } @Override diff --git a/src/newt/classes/jogamp/newt/driver/macosx/ScreenDriver.java b/src/newt/classes/jogamp/newt/driver/macosx/ScreenDriver.java index 5f458e2c9..7c4fa569a 100644 --- a/src/newt/classes/jogamp/newt/driver/macosx/ScreenDriver.java +++ b/src/newt/classes/jogamp/newt/driver/macosx/ScreenDriver.java @@ -77,7 +77,7 @@ public class ScreenDriver extends ScreenImpl { private class CrtProps { CrtProps() { count = getMonitorCount0(); - pixelScaleArray = new int[count]; + pixelScaleArray = new float[count]; propsOrigArray = new int[count][]; propsFixedArray = new int[count][]; @@ -85,8 +85,8 @@ public class ScreenDriver extends ScreenImpl { // Gather whole topology of monitors (NSScreens) // for(int crtIdx=0; crtIdx<count; crtIdx++) { - final float pixelScaleRaw = (float) OSXUtil.GetPixelScale(crtIdx); - pixelScaleArray[crtIdx] = FloatUtil.isZero(pixelScaleRaw, FloatUtil.EPSILON) ? 1 : (int)pixelScaleRaw; + final float pixelScaleRaw = (float)OSXUtil.GetPixelScaleByScreenIdx(crtIdx); + pixelScaleArray[crtIdx] = FloatUtil.isZero(pixelScaleRaw, FloatUtil.EPSILON) ? 1.0f : pixelScaleRaw; propsOrigArray[crtIdx] = getMonitorProps0(crtIdx); if ( null == propsOrigArray[crtIdx] ) { throw new InternalError("Could not gather device props "+crtIdx+"/"+count); @@ -105,7 +105,7 @@ public class ScreenDriver extends ScreenImpl { final int[] thisMonitorProps = propsFixedArray[crtIdx]; final int x = thisMonitorProps[MonitorModeProps.IDX_MONITOR_DEVICE_VIEWPORT+0]; final int y = thisMonitorProps[MonitorModeProps.IDX_MONITOR_DEVICE_VIEWPORT+1]; - final int thisPixelScale = pixelScaleArray[crtIdx]; + final float thisPixelScale = pixelScaleArray[crtIdx]; thisMonitorProps[MonitorModeProps.IDX_MONITOR_DEVICE_VIEWPORT+2] *= thisPixelScale; // fix width thisMonitorProps[MonitorModeProps.IDX_MONITOR_DEVICE_VIEWPORT+3] *= thisPixelScale; // fix height if( 0 != x ) { @@ -129,7 +129,7 @@ public class ScreenDriver extends ScreenImpl { } } final int count; - final int[] pixelScaleArray; + final float[] pixelScaleArray; final int[][] propsOrigArray; final int[][] propsFixedArray; } @@ -167,12 +167,15 @@ public class ScreenDriver extends ScreenImpl { throw new InternalError("Could not gather current mode of device "+crtIdx+"/"+crtProps.count+", but gathered "+modeIdx+" modes"); } // merge monitor-props + supported modes - MonitorModeProps.streamInMonitorDevice(null, cache, this, supportedModes, currentMode, crtProps.propsFixedArray[crtIdx], 0); + final float pixelScale = crtProps.pixelScaleArray[crtIdx]; + MonitorModeProps.streamInMonitorDevice(cache, this, currentMode, + new float[] { pixelScale, pixelScale }, + supportedModes, crtProps.propsFixedArray[crtIdx], 0, null); } } @Override - protected boolean updateNativeMonitorDeviceViewportImpl(final MonitorDevice monitor, final Rectangle viewportPU, final Rectangle viewportWU) { + protected boolean updateNativeMonitorDeviceViewportImpl(final MonitorDevice monitor, final float[] pixelScale, final Rectangle viewportPU, final Rectangle viewportWU) { final CrtProps crtProps = new CrtProps(); final int crtIdx = monitor.getId(); if( 0 > crtIdx || crtIdx >= crtProps.count ) { @@ -182,6 +185,9 @@ public class ScreenDriver extends ScreenImpl { int offset = MonitorModeProps.IDX_MONITOR_DEVICE_VIEWPORT; viewportPU.set(fixedMonitorProps[offset++], fixedMonitorProps[offset++], fixedMonitorProps[offset++], fixedMonitorProps[offset++]); viewportWU.set(fixedMonitorProps[offset++], fixedMonitorProps[offset++], fixedMonitorProps[offset++], fixedMonitorProps[offset++]); + final float _pixelScale = crtProps.pixelScaleArray[crtIdx]; + pixelScale[0] = _pixelScale; + pixelScale[1] = _pixelScale; return true; } diff --git a/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java index c0f7d3859..a57bb5ac6 100644 --- a/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java +++ b/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java @@ -67,20 +67,26 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl public WindowDriver() { } - private boolean updatePixelScale(final boolean sendEvent, final boolean defer, final float newPixelScaleRaw, final float nativePixelScaleRaw) { - final int[] newPixelScale = new int[2]; + private boolean updatePixelScale(final boolean sendEvent, final boolean defer, final boolean deferOffThread, + final float newPixelScaleRaw, final float maxPixelScaleRaw) { + final float[] newPixelScale = new float[2]; { - final int _newPixelScale = FloatUtil.isZero(newPixelScaleRaw, FloatUtil.EPSILON) ? ScalableSurface.IDENTITY_PIXELSCALE : (int) newPixelScaleRaw; + final float _newPixelScale = FloatUtil.isZero(newPixelScaleRaw, FloatUtil.EPSILON) ? ScalableSurface.IDENTITY_PIXELSCALE : 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; + final float _maxPixelScale = FloatUtil.isZero(maxPixelScaleRaw, FloatUtil.EPSILON) ? ScalableSurface.IDENTITY_PIXELSCALE : maxPixelScaleRaw; + maxPixelScale[0]= _maxPixelScale; + maxPixelScale[1]= _maxPixelScale; } + // We keep minPixelScale at [1f, 1f]! - if( SurfaceScaleUtils.computePixelScale(hasPixelScale, hasPixelScale, reqPixelScale, newPixelScale, DEBUG_IMPLEMENTATION ? getClass().getName() : null) ) { + if( SurfaceScaleUtils.setNewPixelScale(hasPixelScale, hasPixelScale, newPixelScale, minPixelScale, maxPixelScale, DEBUG_IMPLEMENTATION ? getClass().getName() : null) ) { if( sendEvent ) { - super.sizeChanged(defer, getWidth(), getHeight(), true); + if( deferOffThread ) { + superSizeChangedOffThread(defer, getWidth(), getHeight(), true); + } else { + super.sizeChanged(defer, getWidth(), getHeight(), true); + } } else { defineSize(getWidth(), getHeight()); } @@ -91,34 +97,34 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl } private boolean updatePixelScaleByScreenIdx(final boolean sendEvent) { - final float nativePixelScaleRaw = (float) OSXUtil.GetPixelScale(getScreen().getIndex()); + final float maxPixelScaleRaw = (float) OSXUtil.GetPixelScaleByScreenIdx(getScreen().getIndex()); if( DEBUG_IMPLEMENTATION ) { - System.err.println("WindowDriver.updatePixelScale.1: "+hasPixelScale[0]+", "+nativePixelScaleRaw+" (native)"); + System.err.println("WindowDriver.updatePixelScale.1: "+hasPixelScale[0]+", "+maxPixelScaleRaw+" (max)"); } - return updatePixelScale(sendEvent, true /* defer */, nativePixelScaleRaw, nativePixelScaleRaw); + return updatePixelScale(sendEvent, true /* defer */, false /*offthread */, maxPixelScaleRaw, maxPixelScaleRaw); } private boolean updatePixelScaleByWindowHandle(final boolean sendEvent) { final long handle = getWindowHandle(); if( 0 != handle ) { - final float nativePixelScaleRaw = (float)OSXUtil.GetPixelScale(handle); + final float maxPixelScaleRaw = (float)OSXUtil.GetPixelScale(handle); if( DEBUG_IMPLEMENTATION ) { - System.err.println("WindowDriver.updatePixelScale.2: "+hasPixelScale[0]+", "+nativePixelScaleRaw+" (native)"); + System.err.println("WindowDriver.updatePixelScale.2: "+hasPixelScale[0]+", "+maxPixelScaleRaw+" (max)"); } - return updatePixelScale(sendEvent, true /* defer */, nativePixelScaleRaw, nativePixelScaleRaw); + return updatePixelScale(sendEvent, true /* defer */, false /*offthread */, maxPixelScaleRaw, maxPixelScaleRaw); } else { return false; } } /** Called from native code */ - protected void updatePixelScale(final boolean defer, final float newPixelScaleRaw, final float nativePixelScaleRaw) { + protected void updatePixelScale(final boolean defer, final float newPixelScaleRaw, final float maxPixelScaleRaw) { final long handle = getWindowHandle(); if( DEBUG_IMPLEMENTATION ) { - System.err.println("WindowDriver.updatePixelScale.3: "+hasPixelScale[0]+" (has) -> "+newPixelScaleRaw+" (raw), "+nativePixelScaleRaw+" (native), drop "+(0==handle)); + System.err.println("WindowDriver.updatePixelScale.3: "+hasPixelScale[0]+" (has) -> "+newPixelScaleRaw+" (new), "+maxPixelScaleRaw+" (max), drop "+(0==handle)); } if( 0 != handle ) { - updatePixelScale(true /* sendEvent*/, defer, newPixelScaleRaw, nativePixelScaleRaw); + updatePixelScale(true /* sendEvent*/, defer, true /*offthread */, newPixelScaleRaw, maxPixelScaleRaw); } } @@ -139,44 +145,47 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl } @Override - public final void setSurfaceScale(final int[] pixelScale) { - SurfaceScaleUtils.validateReqPixelScale(reqPixelScale, pixelScale, DEBUG_IMPLEMENTATION ? getClass().getName() : null); + public final boolean setSurfaceScale(final float[] pixelScale) { + super.setSurfaceScale(pixelScale); - final int[] resPixelScale; + boolean changed = false; if( isNativeValid() ) { if( isOffscreenInstance ) { final NativeWindow pWin = getParent(); if( pWin instanceof ScalableSurface ) { final ScalableSurface sSurf = (ScalableSurface)pWin; sSurf.setSurfaceScale(reqPixelScale); - final int[] pPixelScale = sSurf.getCurrentSurfaceScale(new int[2]); - sSurf.getNativeSurfaceScale(nativePixelScale); - updatePixelScale(true /* sendEvent */, true /* defer */, pPixelScale[0], nativePixelScale[0]); // HiDPI: uniformPixelScale + sSurf.getMaximumSurfaceScale(maxPixelScale); + sSurf.getMinimumSurfaceScale(minPixelScale); + final float[] pPixelScale = sSurf.getCurrentSurfaceScale(new float[2]); + changed = updatePixelScale(true /* sendEvent */, true /* defer */, true /*offthread */, pPixelScale[0], maxPixelScale[0]); // HiDPI: uniformPixelScale } else { // just notify updated pixelScale if offscreen - SurfaceScaleUtils.replaceAutoMaxWithPlatformMax(reqPixelScale); - updatePixelScale(true /* sendEvent */, true /* defer */, reqPixelScale[0], nativePixelScale[0]); // HiDPI: uniformPixelScale + changed = updatePixelScale(true /* sendEvent */, true /* defer */, true /*offthread */, reqPixelScale[0], maxPixelScale[0]); // HiDPI: uniformPixelScale } } else { - // set pixelScale in native code, will issue an update PixelScale - OSXUtil.RunOnMainThread(true, false, new Runnable() { - @Override - public void run() { - setPixelScale0(getWindowHandle(), surfaceHandle, reqPixelScale[0]); // HiDPI: uniformPixelScale - } - } ); + // set pixelScale in native code, will issue an update updatePixelScale(..) + // hence we pre-query whether pixel-scale will change, without affecting current state 'hasPixelScale'! + final float[] _hasPixelScale = new float[2]; + System.arraycopy(hasPixelScale, 0, _hasPixelScale, 0, 2); + if( SurfaceScaleUtils.setNewPixelScale(_hasPixelScale, _hasPixelScale, reqPixelScale, minPixelScale, maxPixelScale, DEBUG_IMPLEMENTATION ? getClass().getName() : null) ) { + OSXUtil.RunOnMainThread(true, false, new Runnable() { + @Override + public void run() { + setPixelScale0(getWindowHandle(), surfaceHandle, _hasPixelScale[0]); // HiDPI: uniformPixelScale + } + } ); + changed = true; + } } - resPixelScale = hasPixelScale; - } else { - hasPixelScale[0] = ScalableSurface.IDENTITY_PIXELSCALE; - hasPixelScale[1] = ScalableSurface.IDENTITY_PIXELSCALE; - resPixelScale = reqPixelScale; } if( DEBUG_IMPLEMENTATION ) { - System.err.println("WindowDriver.setPixelScale: "+pixelScale[0]+"x"+pixelScale[1]+" (req) -> "+ - reqPixelScale[0]+"x"+reqPixelScale[1]+" (validated) -> "+ - resPixelScale[0]+"x"+resPixelScale[1]+" (result) - realized "+isNativeValid()); + System.err.println("WindowDriver.setPixelScale: min["+minPixelScale[0]+", "+minPixelScale[1]+"], max["+ + maxPixelScale[0]+", "+maxPixelScale[1]+"], req["+ + reqPixelScale[0]+", "+reqPixelScale[1]+"] -> result["+ + hasPixelScale[0]+", "+hasPixelScale[1]+"] - changed "+changed+", realized "+isNativeValid()); } + return changed; } @Override @@ -360,13 +369,23 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl System.err.println("MacWindow: sizeChanged() parent["+useParent+" "+x+"/"+y+"] "+getX()+"/"+getY()+" "+newWidth+"x"+newHeight+" -> "+p0S+" screen-client-pos"); } OSXUtil.RunOnMainThread(false, false, new Runnable() { - @Override - public void run() { - setWindowClientTopLeftPoint0(getWindowHandle(), p0S.getX(), p0S.getY(), isVisible()); - } } ); + @Override + public void run() { + setWindowClientTopLeftPoint0(getWindowHandle(), p0S.getX(), p0S.getY(), isVisible()); + } } ); } } - super.sizeChanged(defer, newWidth, newHeight, force); + superSizeChangedOffThread(defer, newWidth, newHeight, force); + } + private void superSizeChangedOffThread(final boolean defer, final int newWidth, final int newHeight, final boolean force) { + if( defer ) { + new Thread() { + public void run() { + WindowDriver.super.sizeChanged(false /* defer */, newWidth, newHeight, force); + } }.start(); + } else { + WindowDriver.super.sizeChanged(false /* defer */, newWidth, newHeight, force); + } } @Override @@ -556,14 +575,18 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl @Override protected void warpPointerImpl(final int x, final int y) { if( !isOffscreenInstance ) { - warpPointer0(getWindowHandle(), x / getPixelScaleX(), y / getPixelScaleY()); + warpPointer0(getWindowHandle(), + SurfaceScaleUtils.scaleInv(x, getPixelScaleX()), + SurfaceScaleUtils.scaleInv(y, getPixelScaleY())); } // else may need offscreen solution ? FIXME } @Override protected final void doMouseEvent(final boolean enqueue, final boolean wait, final short eventType, final int modifiers, final int x, final int y, final short button, final float[] rotationXYZ, final float rotationScale) { - super.doMouseEvent(enqueue, wait, eventType, modifiers, x * getPixelScaleX(), y * getPixelScaleY(), button, rotationXYZ, rotationScale); + super.doMouseEvent(enqueue, wait, eventType, modifiers, + SurfaceScaleUtils.scale(x, getPixelScaleX()), + SurfaceScaleUtils.scale(y, getPixelScaleY()), button, rotationXYZ, rotationScale); } @Override diff --git a/src/newt/classes/jogamp/newt/driver/windows/ScreenDriver.java b/src/newt/classes/jogamp/newt/driver/windows/ScreenDriver.java index 38acd03ae..79ba623f8 100644 --- a/src/newt/classes/jogamp/newt/driver/windows/ScreenDriver.java +++ b/src/newt/classes/jogamp/newt/driver/windows/ScreenDriver.java @@ -106,7 +106,7 @@ public class ScreenDriver extends ScreenImpl { if ( null != currentMode ) { // enabled final int[] monitorProps = getMonitorDevice0(adapterName, crtIdx); // merge monitor-props + supported modes - MonitorModeProps.streamInMonitorDevice(null, cache, this, supportedModes, currentMode, monitorProps, 0); + MonitorModeProps.streamInMonitorDevice(cache, this, currentMode, null, supportedModes, monitorProps, 0, null); // next monitor, 1st mode supportedModes= new ArrayHashSet<MonitorMode>(); @@ -118,7 +118,7 @@ public class ScreenDriver extends ScreenImpl { } @Override - protected boolean updateNativeMonitorDeviceViewportImpl(final MonitorDevice monitor, final Rectangle viewportPU, final Rectangle viewportWU) { + protected boolean updateNativeMonitorDeviceViewportImpl(final MonitorDevice monitor, final float[] pixelScale, final Rectangle viewportPU, final Rectangle viewportWU) { final String adapterName = getAdapterName(monitor.getId()); if( null != adapterName ) { final String activeMonitorName = getActiveMonitorName(adapterName, 0); diff --git a/src/newt/classes/jogamp/newt/driver/x11/ScreenDriver.java b/src/newt/classes/jogamp/newt/driver/x11/ScreenDriver.java index f7361740e..1ec91dce2 100644 --- a/src/newt/classes/jogamp/newt/driver/x11/ScreenDriver.java +++ b/src/newt/classes/jogamp/newt/driver/x11/ScreenDriver.java @@ -152,7 +152,7 @@ public class ScreenDriver extends ScreenImpl { if( null != monitorProps && MonitorModeProps.MIN_MONITOR_DEVICE_PROPERTIES <= monitorProps[0] && // Enabled ? I.e. contains active modes ? MonitorModeProps.MIN_MONITOR_DEVICE_PROPERTIES <= monitorProps.length ) { - MonitorModeProps.streamInMonitorDevice(null, cache, this, monitorProps, 0); + MonitorModeProps.streamInMonitorDevice(cache, this, null, monitorProps, 0, null); } } } @@ -166,7 +166,7 @@ public class ScreenDriver extends ScreenImpl { } @Override - protected boolean updateNativeMonitorDeviceViewportImpl(final MonitorDevice monitor, final Rectangle viewportPU, final Rectangle viewportWU) { + protected boolean updateNativeMonitorDeviceViewportImpl(final MonitorDevice monitor, final float[] pixelScale, final Rectangle viewportPU, final Rectangle viewportWU) { final AbstractGraphicsDevice device = getDisplay().getGraphicsDevice(); device.lock(); try { diff --git a/src/newt/native/MacWindow.m b/src/newt/native/MacWindow.m index 2bd11da3c..1dbe2b7bd 100644 --- a/src/newt/native/MacWindow.m +++ b/src/newt/native/MacWindow.m @@ -420,7 +420,7 @@ NS_ENDHANDLER CGDirectDisplayID NewtScreen_getCGDirectDisplayIDByNSScreen(NSScreen *screen) { - // Mind: typedef uint32_t CGDirectDisplayID; - however, we assume it's 64bit on 64bit ?! + // Mind: typedef uint32_t CGDirectDisplayID; NSDictionary * dict = [screen deviceDescription]; NSNumber * val = (NSNumber *) [dict objectForKey: @"NSScreenNumber"]; // [NSNumber integerValue] returns NSInteger which is 32 or 64 bit native size diff --git a/src/newt/native/NewtMacWindow.m b/src/newt/native/NewtMacWindow.m index caf9e54e0..7b3df391d 100644 --- a/src/newt/native/NewtMacWindow.m +++ b/src/newt/native/NewtMacWindow.m @@ -784,11 +784,21 @@ static jmethodID windowRepaintID = NULL; [super viewDidChangeBackingProperties]; // HiDPI scaling - BOOL useHiDPI = [self wantsBestResolutionOpenGLSurface]; - 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]; + BOOL useHiDPI = false; + CGFloat maxPixelScale = 1.0; + CGFloat winPixelScale = 1.0; + NSWindow* window = [self window]; + NSScreen* screen = [window screen]; +NS_DURING + maxPixelScale = [screen backingScaleFactor]; + useHiDPI = [self wantsBestResolutionOpenGLSurface]; + if( useHiDPI ) { + winPixelScale = [window backingScaleFactor]; + } +NS_HANDLER +NS_ENDHANDLER + DBG_PRINT("viewDidChangeBackingProperties: PixelScale: HiDPI %d, max %f, window %f\n", useHiDPI, (float)maxPixelScale, (float)winPixelScale); + [[self layer] setContentsScale: winPixelScale]; if (javaWindowObject == NULL) { DBG_PRINT("viewDidChangeBackingProperties: null javaWindowObject\n"); @@ -801,7 +811,7 @@ static jmethodID windowRepaintID = NULL; return; } - (*env)->CallVoidMethod(env, javaWindowObject, updatePixelScaleID, JNI_TRUE, (jfloat)pixelScaleUse, (jfloat)pixelScaleNative); // defer + (*env)->CallVoidMethod(env, javaWindowObject, updatePixelScaleID, JNI_TRUE, (jfloat)winPixelScale, (jfloat)maxPixelScale); // defer // detaching thread not required - daemon // NewtCommon_ReleaseJNIEnv(shallBeDetached); 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 685e3bd86..db838fe07 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 @@ -7,7 +7,6 @@ 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; @@ -672,7 +671,7 @@ public class GPUUISceneGLListener0A implements GLEventListener { dpiH = surfacePixelsPerMM[1]*25.4f; System.err.println("Monitor detected: "+mm); 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 scale: native "+Arrays.toString(upWin.getMaximumSurfaceScale(new float[2]))+", current "+Arrays.toString(upWin.getCurrentSurfaceScale(new float[2]))); System.err.println("Surface dpi: "+dpiH); } else { System.err.println("Using default DPI of "+dpiH); 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 274fbea2a..f70f178f3 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 @@ -30,7 +30,7 @@ public class GPUUISceneNewtCanvasAWTDemo { static boolean GraphMSAAMode = false; static float GraphAutoMode = GPUUISceneGLListener0A.DefaultNoAADPIThreshold; - static int[] reqSurfacePixelScale = new int[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE }; + static float[] reqSurfacePixelScale = new float[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE }; static void setComponentSize(final Component comp, final DimensionImmutable new_sz) { try { @@ -91,7 +91,7 @@ public class GPUUISceneNewtCanvasAWTDemo { y = MiscUtils.atoi(args[i], y); } else if(args[i].equals("-pixelScale")) { i++; - final int pS = MiscUtils.atoi(args[i], reqSurfacePixelScale[0]); + final float pS = MiscUtils.atof(args[i], reqSurfacePixelScale[0]); reqSurfacePixelScale[0] = pS; reqSurfacePixelScale[1] = pS; } else if(args[i].equals("-es2")) { @@ -151,10 +151,10 @@ public class GPUUISceneNewtCanvasAWTDemo { window.setSize(width, height); window.setTitle("GraphUI Newt/AWT Demo: graph["+Region.getRenderModeString(rmode)+"], msaa "+SceneMSAASamples); window.setSurfaceScale(reqSurfacePixelScale); - final int[] valReqSurfacePixelScale = window.getRequestedSurfaceScale(new int[2]); + final float[] valReqSurfacePixelScale = window.getRequestedSurfaceScale(new float[2]); final GPUUISceneGLListener0A sceneGLListener = 0 < GraphAutoMode ? new GPUUISceneGLListener0A(GraphAutoMode, DEBUG, TRACE) : - new GPUUISceneGLListener0A(rmode, DEBUG, TRACE); + new GPUUISceneGLListener0A(rmode, DEBUG, TRACE); window.addGLEventListener(sceneGLListener); sceneGLListener.attachInputListenerTo(window); @@ -180,7 +180,7 @@ public class GPUUISceneNewtCanvasAWTDemo { frame.setVisible(true); } }); - final int[] hasSurfacePixelScale1 = window.getCurrentSurfaceScale(new int[2]); + final float[] hasSurfacePixelScale1 = window.getCurrentSurfaceScale(new float[2]); System.err.println("HiDPI PixelScale: "+reqSurfacePixelScale[0]+"x"+reqSurfacePixelScale[1]+" (req) -> "+ valReqSurfacePixelScale[0]+"x"+valReqSurfacePixelScale[1]+" (val) -> "+ hasSurfacePixelScale1[0]+"x"+hasSurfacePixelScale1[1]+" (has)"); diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneNewtDemo.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneNewtDemo.java index 16d56a041..29705d35b 100644 --- a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneNewtDemo.java +++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneNewtDemo.java @@ -20,7 +20,7 @@ public class GPUUISceneNewtDemo { static boolean GraphMSAAMode = false; static float GraphAutoMode = GPUUISceneGLListener0A.DefaultNoAADPIThreshold; - static int[] reqSurfacePixelScale = new int[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE }; + static float[] reqSurfacePixelScale = new float[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE }; public static void main(final String[] args) { int width = 800, height = 400; @@ -66,7 +66,7 @@ public class GPUUISceneNewtDemo { y = MiscUtils.atoi(args[i], y); } else if(args[i].equals("-pixelScale")) { i++; - final int pS = MiscUtils.atoi(args[i], reqSurfacePixelScale[0]); + final float pS = MiscUtils.atof(args[i], reqSurfacePixelScale[0]); reqSurfacePixelScale[0] = pS; reqSurfacePixelScale[1] = pS; } else if(args[i].equals("-es2")) { @@ -126,7 +126,7 @@ public class GPUUISceneNewtDemo { 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]); + final float[] valReqSurfacePixelScale = window.getRequestedSurfaceScale(new float[2]); final GPUUISceneGLListener0A sceneGLListener = 0 < GraphAutoMode ? new GPUUISceneGLListener0A(GraphAutoMode, DEBUG, TRACE) : new GPUUISceneGLListener0A(rmode, DEBUG, TRACE); @@ -145,7 +145,7 @@ public class GPUUISceneNewtDemo { }); window.setVisible(true); - final int[] hasSurfacePixelScale1 = window.getCurrentSurfaceScale(new int[2]); + final float[] hasSurfacePixelScale1 = window.getCurrentSurfaceScale(new float[2]); System.err.println("HiDPI PixelScale: "+reqSurfacePixelScale[0]+"x"+reqSurfacePixelScale[1]+" (req) -> "+ valReqSurfacePixelScale[0]+"x"+valReqSurfacePixelScale[1]+" (val) -> "+ hasSurfacePixelScale1[0]+"x"+hasSurfacePixelScale1[1]+" (has)"); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestAWT03GLCanvasRecreate01.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestAWT03GLCanvasRecreate01.java index b074297e2..032cf4fe7 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestAWT03GLCanvasRecreate01.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestAWT03GLCanvasRecreate01.java @@ -40,6 +40,8 @@ import java.awt.Dimension; import java.awt.Frame; import java.awt.Label; +import jogamp.nativewindow.SurfaceScaleUtils; + import org.junit.Assert; import org.junit.Assume; import org.junit.Before; @@ -178,8 +180,8 @@ public class TestAWT03GLCanvasRecreate01 extends UITestCase { } private void assertSize(final Dimension expSize) { - final int[] scale = { 1, 1 }; - glComp.getNativeSurfaceScale(scale); + final float[] scale = { 1f, 1f }; + glComp.getMaximumSurfaceScale(scale); final Dimension hasSize = glComp.getSize(null); @@ -188,8 +190,8 @@ public class TestAWT03GLCanvasRecreate01 extends UITestCase { Assert.assertTrue("AWT Size.height mismatch: expected "+expSize+", has "+hasSize, Math.abs(expSize.height-hasSize.height) <= sizeEps); - final int expSurfWidth = expSize.width * scale[0]; - final int expSurfHeight = expSize.height * scale[0]; + final int expSurfWidth = SurfaceScaleUtils.scale(expSize.width, scale[0]); + final int expSurfHeight = SurfaceScaleUtils.scale(expSize.height, scale[0]); final int hasSurfWidth = glComp.getSurfaceWidth(); final int hasSurfHeight = glComp.getSurfaceHeight(); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestAWT03GLJPanelRecreate01.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestAWT03GLJPanelRecreate01.java index b2d487784..c4d9633b3 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestAWT03GLJPanelRecreate01.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestAWT03GLJPanelRecreate01.java @@ -41,6 +41,8 @@ import com.jogamp.opengl.test.junit.util.MiscUtils; import java.awt.BorderLayout; import java.awt.Dimension; +import jogamp.nativewindow.SurfaceScaleUtils; + import org.junit.Assert; import org.junit.Assume; import org.junit.Before; @@ -179,8 +181,8 @@ public class TestAWT03GLJPanelRecreate01 extends UITestCase { } private void assertSize(final Dimension expSize) { - final int[] scale = { 1, 1 }; - glComp.getNativeSurfaceScale(scale); + final float[] scale = { 1f, 1f }; + glComp.getMaximumSurfaceScale(scale); final Dimension hasSize = glComp.getSize(null); @@ -189,8 +191,8 @@ public class TestAWT03GLJPanelRecreate01 extends UITestCase { Assert.assertTrue("AWT Size.height mismatch: expected "+expSize+", has "+hasSize, Math.abs(expSize.height-hasSize.height) <= sizeEps); - final int expSurfWidth = expSize.width * scale[0]; - final int expSurfHeight = expSize.height * scale[0]; + final int expSurfWidth = SurfaceScaleUtils.scale(expSize.width, scale[0]); + final int expSurfHeight = SurfaceScaleUtils.scale(expSize.height, scale[0]); final int hasSurfWidth = glComp.getSurfaceWidth(); final int hasSurfHeight = glComp.getSurfaceHeight(); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/TestGearsES2AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/TestGearsES2AWT.java index d8c4341a8..6d682bb2c 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/TestGearsES2AWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/TestGearsES2AWT.java @@ -55,8 +55,6 @@ import java.awt.Dimension; import java.awt.EventQueue; import java.awt.Frame; import java.awt.TextArea; -import java.awt.event.ComponentEvent; -import java.awt.event.ComponentListener; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; @@ -80,7 +78,7 @@ public class TestGearsES2AWT extends UITestCase { static int xpos = 10, ypos = 10; static FrameLayout frameLayout = FrameLayout.None; static ResizeBy resizeBy = ResizeBy.Component; - static int[] reqSurfacePixelScale = new int[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE }; + static float[] reqSurfacePixelScale = new float[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE }; static boolean forceES2 = false; static boolean forceGL3 = false; @@ -171,7 +169,7 @@ public class TestGearsES2AWT extends UITestCase { Assert.assertNotNull(glCanvas); setSize(resizeBy, frame, false, glCanvas, new Dimension(width, height)); glCanvas.setSurfaceScale(reqSurfacePixelScale); - final int[] valReqSurfacePixelScale = glCanvas.getRequestedSurfaceScale(new int[2]); + final float[] valReqSurfacePixelScale = glCanvas.getRequestedSurfaceScale(new float[2]); frame.setLocation(xpos, ypos); switch( frameLayout) { @@ -215,29 +213,23 @@ public class TestGearsES2AWT extends UITestCase { } setTitle(frame, glCanvas, caps); - frame.addComponentListener(new ComponentListener() { - @Override - public void componentResized(final ComponentEvent e) { - setTitle(frame, glCanvas, caps); - } - - @Override - public void componentMoved(final ComponentEvent e) { - setTitle(frame, glCanvas, caps); - } - - @Override - public void componentShown(final ComponentEvent e) { } - - @Override - public void componentHidden(final ComponentEvent e) { } - }); - final GearsES2 demo = new GearsES2(swapInterval); glCanvas.addGLEventListener(demo); final SnapshotGLEventListener snap = new SnapshotGLEventListener(); glCanvas.addGLEventListener(snap); + glCanvas.addGLEventListener(new GLEventListener() { + @Override + public void init(final GLAutoDrawable drawable) { } + @Override + public void dispose(final GLAutoDrawable drawable) { } + @Override + public void display(final GLAutoDrawable drawable) { } + @Override + public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) { + setTitle(frame, glCanvas, caps); + } + }); final Animator animator = useAnimator ? new Animator(glCanvas) : null; if( useAnimator && exclusiveContext ) { @@ -254,24 +246,22 @@ public class TestGearsES2AWT extends UITestCase { return; } if(e.getKeyChar()=='x') { - final int[] hadSurfacePixelScale = glCanvas.getCurrentSurfaceScale(new int[2]); - final int[] reqSurfacePixelScale; + final float[] hadSurfacePixelScale = glCanvas.getCurrentSurfaceScale(new float[2]); + final float[] reqSurfacePixelScale; if( hadSurfacePixelScale[0] == ScalableSurface.IDENTITY_PIXELSCALE ) { - reqSurfacePixelScale = new int[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE }; + reqSurfacePixelScale = new float[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE }; } else { - reqSurfacePixelScale = new int[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE }; + reqSurfacePixelScale = new float[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE }; } System.err.println("[set PixelScale pre]: had "+hadSurfacePixelScale[0]+"x"+hadSurfacePixelScale[1]+" -> req "+reqSurfacePixelScale[0]+"x"+reqSurfacePixelScale[1]); glCanvas.setSurfaceScale(reqSurfacePixelScale); - final int[] valReqSurfacePixelScale = glCanvas.getRequestedSurfaceScale(new int[2]); - final int[] hasSurfacePixelScale0 = glCanvas.getNativeSurface().convertToPixelUnits(new int[] { 1, 1 }); - final int[] hasSurfacePixelScale1 = glCanvas.getCurrentSurfaceScale(new int[2]); + final float[] valReqSurfacePixelScale = glCanvas.getRequestedSurfaceScale(new float[2]); + final float[] hasSurfacePixelScale1 = glCanvas.getCurrentSurfaceScale(new float[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) -> "+ hasSurfacePixelScale1[0]+"x"+hasSurfacePixelScale1[1]+" (has)"); setTitle(frame, glCanvas, caps); - Assert.assertArrayEquals(hasSurfacePixelScale0, hasSurfacePixelScale1); } } }; new AWTKeyAdapter(kl, glCanvas).addTo(glCanvas); @@ -288,13 +278,11 @@ public class TestGearsES2AWT extends UITestCase { Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true)); Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glCanvas, true)); - final int[] hasSurfacePixelScale0 = glCanvas.getNativeSurface().convertToPixelUnits(new int[] { 1, 1 }); - final int[] hasSurfacePixelScale1 = glCanvas.getCurrentSurfaceScale(new int[2]); + final float[] hasSurfacePixelScale1 = glCanvas.getCurrentSurfaceScale(new float[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(frame, glCanvas, caps); - Assert.assertArrayEquals(hasSurfacePixelScale0, hasSurfacePixelScale1); if( useAnimator ) { animator.start(); @@ -446,7 +434,7 @@ public class TestGearsES2AWT extends UITestCase { rh = MiscUtils.atoi(args[i], rh); } else if(args[i].equals("-pixelScale")) { i++; - final int pS = MiscUtils.atoi(args[i], reqSurfacePixelScale[0]); + final float pS = MiscUtils.atof(args[i], reqSurfacePixelScale[0]); reqSurfacePixelScale[0] = pS; reqSurfacePixelScale[1] = pS; } else if(args[i].equals("-layout")) { diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/TestGearsES2GLJPanelAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/TestGearsES2GLJPanelAWT.java index 340816a13..0f2b89128 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/TestGearsES2GLJPanelAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/TestGearsES2GLJPanelAWT.java @@ -33,11 +33,8 @@ import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.DisplayMode; import java.awt.GraphicsDevice; -import java.awt.event.ComponentEvent; -import java.awt.event.ComponentListener; import java.lang.reflect.InvocationTargetException; -import javax.media.nativewindow.NativeSurface; import javax.media.nativewindow.ScalableSurface; import javax.media.nativewindow.util.Rectangle; import javax.media.nativewindow.util.RectangleImmutable; @@ -50,8 +47,6 @@ import javax.media.opengl.awt.GLJPanel; import javax.swing.JFrame; import javax.swing.SwingUtilities; -import jogamp.common.os.PlatformPropsImpl; - import org.junit.AfterClass; import org.junit.Assert; import org.junit.Assume; @@ -60,8 +55,13 @@ import org.junit.Test; import org.junit.FixMethodOrder; import org.junit.runners.MethodSorters; -import com.jogamp.common.os.Platform; +import com.jogamp.newt.Display; +import com.jogamp.newt.MonitorDevice; +import com.jogamp.newt.NewtFactory; +import com.jogamp.newt.Screen; import com.jogamp.newt.event.KeyEvent; +import com.jogamp.newt.event.MonitorEvent; +import com.jogamp.newt.event.MonitorModeListener; import com.jogamp.newt.event.TraceKeyAdapter; import com.jogamp.newt.event.TraceWindowAdapter; import com.jogamp.newt.event.awt.AWTKeyAdapter; @@ -90,7 +90,7 @@ public class TestGearsES2GLJPanelAWT extends UITestCase { static boolean manualTest = false; static boolean skipGLOrientationVerticalFlip = false; static int xpos = 10, ypos = 10; - static int[] reqSurfacePixelScale = new int[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE }; + static float[] reqSurfacePixelScale = new float[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE }; @BeforeClass public static void initClass() { @@ -139,7 +139,7 @@ public class TestGearsES2GLJPanelAWT extends UITestCase { glJPanel.setPreferredSize(wsize); glJPanel.setSize(wsize); glJPanel.setSurfaceScale(reqSurfacePixelScale); - final int[] valReqSurfacePixelScale = glJPanel.getRequestedSurfaceScale(new int[2]); + final float[] valReqSurfacePixelScale = glJPanel.getRequestedSurfaceScale(new float[2]); if( caps.isBitmap() || caps.getGLProfile().isGL2() ) { final Gears gears = new Gears(swapInterval); gears.setFlipVerticalInGLOrientation(skipGLOrientationVerticalFlip); @@ -162,29 +162,10 @@ public class TestGearsES2GLJPanelAWT extends UITestCase { public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) { setTitle(frame, glJPanel, caps); } - }); setTitle(frame, glJPanel, caps); frame.setLocation(xpos, ypos); - frame.addComponentListener(new ComponentListener() { - @Override - public void componentResized(final ComponentEvent e) { - setTitle(frame, glJPanel, caps); - } - - @Override - public void componentMoved(final ComponentEvent e) { - setTitle(frame, glJPanel, caps); - } - - @Override - public void componentShown(final ComponentEvent e) { } - - @Override - public void componentHidden(final ComponentEvent e) { } - }); - final FPSAnimator animator = useAnimator ? new FPSAnimator(glJPanel, 60) : null; SwingUtilities.invokeAndWait(new Runnable() { @@ -197,13 +178,11 @@ public class TestGearsES2GLJPanelAWT extends UITestCase { Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true)); Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glJPanel, true)); - final int[] hasSurfacePixelScale0 = glJPanel.getNativeSurface().convertToPixelUnits(new int[] { 1, 1 }); - final int[] hasSurfacePixelScale1 = glJPanel.getCurrentSurfaceScale(new int[2]); + final float[] hasSurfacePixelScale1 = glJPanel.getCurrentSurfaceScale(new float[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(frame, glJPanel, caps); - Assert.assertArrayEquals(hasSurfacePixelScale0, hasSurfacePixelScale1); if( useAnimator ) { animator.setUpdateFPSFrames(60, System.err); @@ -231,31 +210,44 @@ public class TestGearsES2GLJPanelAWT extends UITestCase { System.err.printf("GetPixelScale: NW Screen: %s%n", glJPanel.getNativeSurface().getGraphicsConfiguration().getScreen()); System.err.printf("GetPixelScale: Panel Bounds: %s window-units%n", r.toString()); System.err.printf("GetPixelScale: Panel Resolution: %d x %d pixel-units%n", glJPanel.getSurfaceWidth(), glJPanel.getSurfaceHeight()); - if( Platform.OSType.MACOS == PlatformPropsImpl.OS_TYPE ) { - final int[] screenIndexOut = { 0 }; - final double pixelScale = jogamp.nativewindow.macosx.OSXUtil.GetPixelScale(r, screenIndexOut); - System.err.printf("GetPixelScale: PixelScale %f on screen-idx %d%n", pixelScale, screenIndexOut[0]); + { + final Display dpy = NewtFactory.createDisplay(null); + final Screen screen = NewtFactory.createScreen(dpy, 0); + screen.addReference(); + final MonitorModeListener sml = new MonitorModeListener() { + @Override + public void monitorModeChangeNotify(final MonitorEvent me) { + } + @Override + public void monitorModeChanged(final MonitorEvent me, final boolean success) { + } + }; + screen.addMonitorModeListener(sml); + try { + final MonitorDevice md = screen.getMainMonitor(r); + System.err.printf("GetPixelScale: %s%n", md.toString()); + } finally { + screen.removeReference(); + } } System.err.println(); } else if(e.getKeyChar()=='x') { - final int[] hadSurfacePixelScale = glJPanel.getCurrentSurfaceScale(new int[2]); - final int[] reqSurfacePixelScale; + final float[] hadSurfacePixelScale = glJPanel.getCurrentSurfaceScale(new float[2]); + final float[] reqSurfacePixelScale; if( hadSurfacePixelScale[0] == ScalableSurface.IDENTITY_PIXELSCALE ) { - reqSurfacePixelScale = new int[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE }; + reqSurfacePixelScale = new float[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE }; } else { - reqSurfacePixelScale = new int[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE }; + reqSurfacePixelScale = new float[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE }; } System.err.println("[set PixelScale pre]: had "+hadSurfacePixelScale[0]+"x"+hadSurfacePixelScale[1]+" -> req "+reqSurfacePixelScale[0]+"x"+reqSurfacePixelScale[1]); glJPanel.setSurfaceScale(reqSurfacePixelScale); - final int[] valReqSurfacePixelScale = glJPanel.getRequestedSurfaceScale(new int[2]); - final int[] hasSurfacePixelScale0 = glJPanel.getNativeSurface().convertToPixelUnits(new int[] { 1, 1 }); - final int[] hasSurfacePixelScale1 = glJPanel.getCurrentSurfaceScale(new int[2]); + final float[] valReqSurfacePixelScale = glJPanel.getRequestedSurfaceScale(new float[2]); + final float[] hasSurfacePixelScale1 = glJPanel.getCurrentSurfaceScale(new float[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) -> "+ hasSurfacePixelScale1[0]+"x"+hasSurfacePixelScale1[1]+" (has)"); setTitle(frame, glJPanel, caps); - Assert.assertArrayEquals(hasSurfacePixelScale0, hasSurfacePixelScale1); } else if(e.getKeyChar()=='m') { final GLCapabilitiesImmutable capsPre = glJPanel.getChosenGLCapabilities(); final GLCapabilities capsNew = new GLCapabilities(capsPre.getGLProfile()); @@ -520,7 +512,7 @@ public class TestGearsES2GLJPanelAWT extends UITestCase { rh = MiscUtils.atoi(args[i], rh); } else if(args[i].equals("-pixelScale")) { i++; - final int pS = MiscUtils.atoi(args[i], reqSurfacePixelScale[0]); + final float pS = MiscUtils.atof(args[i], reqSurfacePixelScale[0]); reqSurfacePixelScale[0] = pS; reqSurfacePixelScale[1] = pS; } else if(args[i].equals("-userVFlip")) { 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 eb2536639..3aa1519ab 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 @@ -85,7 +85,7 @@ public class TestGearsES2NEWT extends UITestCase { static int screenIdx = 0; static PointImmutable wpos; static DimensionImmutable wsize, rwsize=null; - static int[] reqSurfacePixelScale = new int[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE }; + static float[] reqSurfacePixelScale = new float[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE }; static long duration = 500; // ms static boolean opaque = true; @@ -137,7 +137,7 @@ public class TestGearsES2NEWT extends UITestCase { final GLWindow glWindow = GLWindow.create(screen, caps); Assert.assertNotNull(glWindow); glWindow.setSurfaceScale(reqSurfacePixelScale); - final int[] valReqSurfacePixelScale = glWindow.getRequestedSurfaceScale(new int[2]); + final float[] valReqSurfacePixelScale = glWindow.getRequestedSurfaceScale(new float[2]); glWindow.setSize(wsize.getWidth(), wsize.getHeight()); if(null != wpos) { glWindow.setPosition(wpos.getX(), wpos.getY()); @@ -392,24 +392,22 @@ public class TestGearsES2NEWT extends UITestCase { glWindow.setExclusiveContextThread(t); } }.start(); } else if(e.getKeyChar()=='x') { - final int[] hadSurfacePixelScale = glWindow.getCurrentSurfaceScale(new int[2]); - final int[] reqSurfacePixelScale; + final float[] hadSurfacePixelScale = glWindow.getCurrentSurfaceScale(new float[2]); + final float[] reqSurfacePixelScale; if( hadSurfacePixelScale[0] == ScalableSurface.IDENTITY_PIXELSCALE ) { - reqSurfacePixelScale = new int[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE }; + reqSurfacePixelScale = new float[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE }; } else { - reqSurfacePixelScale = new int[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE }; + reqSurfacePixelScale = new float[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE }; } System.err.println("[set PixelScale pre]: had "+hadSurfacePixelScale[0]+"x"+hadSurfacePixelScale[1]+" -> req "+reqSurfacePixelScale[0]+"x"+reqSurfacePixelScale[1]); glWindow.setSurfaceScale(reqSurfacePixelScale); - final int[] valReqSurfacePixelScale = glWindow.getRequestedSurfaceScale(new int[2]); - final int[] hasSurfacePixelScale0 = glWindow.convertToPixelUnits(new int[] { 1, 1 }); - final int[] hasSurfacePixelScale1 = glWindow.getCurrentSurfaceScale(new int[2]); + final float[] valReqSurfacePixelScale = glWindow.getRequestedSurfaceScale(new float[2]); + final float[] hasSurfacePixelScale1 = glWindow.getCurrentSurfaceScale(new float[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) -> "+ - hasSurfacePixelScale1[0]+"x"+hasSurfacePixelScale1[1]+" (has)"); + reqSurfacePixelScale[0]+"x"+reqSurfacePixelScale[1]+" (req) -> "+ + valReqSurfacePixelScale[0]+"x"+valReqSurfacePixelScale[1]+" (val) -> "+ + hasSurfacePixelScale1[0]+"x"+hasSurfacePixelScale1[1]+" (has)"); setTitle(glWindow, caps); - Assert.assertArrayEquals(hasSurfacePixelScale0, hasSurfacePixelScale1); } } }); @@ -482,13 +480,11 @@ public class TestGearsES2NEWT extends UITestCase { System.err.println("GL chosen: "+glWindow.getChosenCapabilities()); System.err.println("window pos/siz: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight()+", "+glWindow.getInsets()); - final int[] hasSurfacePixelScale0 = glWindow.convertToPixelUnits(new int[] { 1, 1 }); - final int[] hasSurfacePixelScale1 = glWindow.getCurrentSurfaceScale(new int[2]); + final float[] hasSurfacePixelScale1 = glWindow.getCurrentSurfaceScale(new float[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, caps); - Assert.assertArrayEquals(hasSurfacePixelScale0, hasSurfacePixelScale1); snap.setMakeSnapshot(); @@ -669,7 +665,7 @@ public class TestGearsES2NEWT extends UITestCase { usePos = true; } else if(args[i].equals("-pixelScale")) { i++; - final int pS = MiscUtils.atoi(args[i], reqSurfacePixelScale[0]); + final float pS = MiscUtils.atof(args[i], reqSurfacePixelScale[0]); reqSurfacePixelScale[0] = pS; reqSurfacePixelScale[1] = pS; } else if(args[i].equals("-rwidth")) { 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 2dca3ad5e..7af6fd109 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 @@ -86,7 +86,7 @@ public class TestGearsES2NewtCanvasAWT extends UITestCase { static DimensionImmutable wsize, rwsize = null; static FrameLayout frameLayout = FrameLayout.None; static ResizeBy resizeBy = ResizeBy.Component; - static int[] reqSurfacePixelScale = new int[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE }; + static float[] reqSurfacePixelScale = new float[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE }; static long duration = 500; // ms static boolean opaque = true; @@ -195,7 +195,7 @@ public class TestGearsES2NewtCanvasAWT extends UITestCase { final GLWindow glWindow = GLWindow.create(screen, caps); Assert.assertNotNull(glWindow); glWindow.setSurfaceScale(reqSurfacePixelScale); - final int[] valReqSurfacePixelScale = glWindow.getRequestedSurfaceScale(new int[2]); + final float[] valReqSurfacePixelScale = glWindow.getRequestedSurfaceScale(new float[2]); final NewtCanvasAWT newtCanvasAWT = new NewtCanvasAWT(glWindow); if ( shallUseOffscreenFBOLayer ) { @@ -309,24 +309,22 @@ public class TestGearsES2NewtCanvasAWT extends UITestCase { return; } if(e.getKeyChar()=='x') { - final int[] hadSurfacePixelScale = glWindow.getCurrentSurfaceScale(new int[2]); - final int[] reqSurfacePixelScale; + final float[] hadSurfacePixelScale = glWindow.getCurrentSurfaceScale(new float[2]); + final float[] reqSurfacePixelScale; if( hadSurfacePixelScale[0] == ScalableSurface.IDENTITY_PIXELSCALE ) { - reqSurfacePixelScale = new int[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE }; + reqSurfacePixelScale = new float[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE }; } else { - reqSurfacePixelScale = new int[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE }; + reqSurfacePixelScale = new float[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE }; } System.err.println("[set PixelScale pre]: had "+hadSurfacePixelScale[0]+"x"+hadSurfacePixelScale[1]+" -> req "+reqSurfacePixelScale[0]+"x"+reqSurfacePixelScale[1]); glWindow.setSurfaceScale(reqSurfacePixelScale); - final int[] valReqSurfacePixelScale = glWindow.getRequestedSurfaceScale(new int[2]); - final int[] hasSurfacePixelScale0 = glWindow.convertToPixelUnits(new int[] { 1, 1 }); - final int[] hasSurfacePixelScale1 = glWindow.getCurrentSurfaceScale(new int[2]); + final float[] valReqSurfacePixelScale = glWindow.getRequestedSurfaceScale(new float[2]); + final float[] hasSurfacePixelScale1 = glWindow.getCurrentSurfaceScale(new float[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) -> "+ hasSurfacePixelScale1[0]+"x"+hasSurfacePixelScale1[1]+" (has)"); setTitle(frame, newtCanvasAWT, glWindow, caps); - Assert.assertArrayEquals(hasSurfacePixelScale0, hasSurfacePixelScale1); } } } ); @@ -359,13 +357,11 @@ public class TestGearsES2NewtCanvasAWT extends UITestCase { System.err.println("GL chosen: "+glWindow.getChosenCapabilities()); System.err.println("window pos/siz: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight()+", "+glWindow.getInsets()); - final int[] hasSurfacePixelScale0 = glWindow.convertToPixelUnits(new int[] { 1, 1 }); - final int[] hasSurfacePixelScale1 = glWindow.getCurrentSurfaceScale(new int[2]); + final float[] hasSurfacePixelScale1 = glWindow.getCurrentSurfaceScale(new float[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(frame, newtCanvasAWT, glWindow, caps); - Assert.assertArrayEquals(hasSurfacePixelScale0, hasSurfacePixelScale1); if( null != rwsize ) { Thread.sleep(500); // 500ms delay @@ -503,7 +499,7 @@ public class TestGearsES2NewtCanvasAWT extends UITestCase { usePos = true; } else if(args[i].equals("-pixelScale")) { i++; - final int pS = MiscUtils.atoi(args[i], reqSurfacePixelScale[0]); + final float pS = MiscUtils.atof(args[i], reqSurfacePixelScale[0]); reqSurfacePixelScale[0] = pS; reqSurfacePixelScale[1] = pS; } else if(args[i].equals("-screen")) { 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 e20bbef2d..db3f81701 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 @@ -63,7 +63,7 @@ import org.junit.runners.MethodSorters; @FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestRulerNEWT01 extends UITestCase { static long durationPerTest = 500; // ms - static int[] reqSurfacePixelScale = new int[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE }; + static float[] reqSurfacePixelScale = new float[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE }; static boolean manualTest = false; private void setTitle(final Window win) { @@ -77,7 +77,7 @@ public class TestRulerNEWT01 extends UITestCase { final GLWindow glWindow = GLWindow.create(new GLCapabilities(GLProfile.getGL2ES2())); Assert.assertNotNull(glWindow); glWindow.setSurfaceScale(reqSurfacePixelScale); - final int[] valReqSurfacePixelScale = glWindow.getRequestedSurfaceScale(new int[2]); + final float[] valReqSurfacePixelScale = glWindow.getRequestedSurfaceScale(new float[2]); glWindow.setSize(640, 480); glWindow.addGLEventListener(new GLEventListener() { @@ -183,19 +183,19 @@ public class TestRulerNEWT01 extends UITestCase { return; } if(e.getKeyChar()=='x') { - final int[] hadSurfacePixelScale = glWindow.getCurrentSurfaceScale(new int[2]); - final int[] reqSurfacePixelScale; + final float[] hadSurfacePixelScale = glWindow.getCurrentSurfaceScale(new float[2]); + final float[] reqSurfacePixelScale; if( hadSurfacePixelScale[0] == ScalableSurface.IDENTITY_PIXELSCALE ) { - reqSurfacePixelScale = new int[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE }; + reqSurfacePixelScale = new float[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE }; } else { - reqSurfacePixelScale = new int[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE }; + reqSurfacePixelScale = new float[] { 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]); + final float[] valReqSurfacePixelScale = glWindow.getRequestedSurfaceScale(new float[2]); + final float[] hasSurfacePixelScale = glWindow.getCurrentSurfaceScale(new float[2]); + final float[] nativeSurfacePixelScale = glWindow.getMaximumSurfaceScale(new float[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) -> "+ @@ -208,7 +208,7 @@ public class TestRulerNEWT01 extends UITestCase { glWindow.setVisible(true); - final int[] hasSurfacePixelScale1 = glWindow.getCurrentSurfaceScale(new int[2]); + final float[] hasSurfacePixelScale1 = glWindow.getCurrentSurfaceScale(new float[2]); System.err.println("HiDPI PixelScale: "+reqSurfacePixelScale[0]+"x"+reqSurfacePixelScale[1]+" (req) -> "+ valReqSurfacePixelScale[0]+"x"+valReqSurfacePixelScale[1]+" (val) -> "+ hasSurfacePixelScale1[0]+"x"+hasSurfacePixelScale1[1]+" (has)"); @@ -243,7 +243,7 @@ public class TestRulerNEWT01 extends UITestCase { durationPerTest = MiscUtils.atoi(args[++i], (int)durationPerTest); } else if(args[i].equals("-pixelScale")) { i++; - final int pS = MiscUtils.atoi(args[i], reqSurfacePixelScale[0]); + final float pS = MiscUtils.atof(args[i], reqSurfacePixelScale[0]); reqSurfacePixelScale[0] = pS; reqSurfacePixelScale[1] = pS; } else if(args[i].equals("-manual")) { diff --git a/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode00aNEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode00aNEWT.java index 860560658..059b890e3 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode00aNEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode00aNEWT.java @@ -112,12 +112,12 @@ public class TestScreenMode00aNEWT extends UITestCase { final Rectangle viewport = new Rectangle(0, 0, 1920, 1080); final ArrayHashSet<MonitorMode> supportedModes = new ArrayHashSet<MonitorMode>(); supportedModes.add(modeOut); - final MonitorDevice monOut = new MonitorDeviceImpl(null, -1, sizeMM, viewport, viewport, modeOut, supportedModes); + final MonitorDevice monOut = new MonitorDeviceImpl(null, -1, sizeMM, modeOut, null, viewport, viewport, supportedModes); System.err.println("01 out : "+monOut); cache.monitorDevices.add(monOut); { final int[] props = MonitorModeProps.streamOutMonitorDevice(monOut); - final MonitorDevice monIn = MonitorModeProps.streamInMonitorDevice(null, cache, null, props, 0); + final MonitorDevice monIn = MonitorModeProps.streamInMonitorDevice(cache, null, null, props, 0, null); System.err.println("01 in : "+monIn); Assert.assertEquals(monOut.getCurrentMode(), monOut.getOriginalMode()); |