diff options
author | Sven Gothel <[email protected]> | 2014-06-08 08:11:57 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2014-06-08 08:11:57 +0200 |
commit | 2571ed0b5ef14155d204540d38b564a7d4cd47b6 (patch) | |
tree | 8aaf1171af1b95f1cb1ebe706771a4aff3752c2f /src/newt/classes | |
parent | ff7bf3122fd2007bbe70cfadca9f0f978ee96456 (diff) |
Bug 741 HiDPI: Add ScalableSurface interface to get/set pixelScale w/ full OSX impl.
Add ScalableSurface interface
- To set pixelScale before and after realization
- To get pixelScale
- Implemented on:
- NEWT Window
- Generic impl. in WindowImpl
- OSX WindowDriver impl.
- Also propagetes pixelScale to parent JAWTWindow if offscreen (NewtCanvasAWT)
- AWT WindowDriver impl.
- JAWTWindow / OSXCalayer
- AWT GLCanvas
- AWT GLJPanel
- NEWTCanvasAWT:
- Propagates NEWT Window's pixelScale to underlying JAWTWindow
- WrappedSurface for pixelScale propagation
using offscreen drawables, i.e. GLJPanel
- Generic helper in SurfaceScaleUtils (nativewindow package)
- Fully implemented on OSX
- Capable to switch pixelScale before realization,
i.e. native-creation, as well as on-the-fly.
- Impl. uses int[2] for pixelScale to support
non-uniform scale.
Test cases:
- com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NEWT
- com.jogamp.opengl.test.junit.jogl.demos.es2.awt.TestGearsES2AWT
- com.jogamp.opengl.test.junit.jogl.demos.es2.awt.TestGearsES2GLJPanelAWT
- com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NewtCanvasAWT
- Press 'x' to toggle HiDPI
- Commandline '-pixelScale <value>'
- Added basic auto unit test (setting pre-realization)
Diffstat (limited to 'src/newt/classes')
7 files changed, 126 insertions, 51 deletions
diff --git a/src/newt/classes/com/jogamp/newt/Window.java b/src/newt/classes/com/jogamp/newt/Window.java index 82199e9b5..88134f3ef 100644 --- a/src/newt/classes/com/jogamp/newt/Window.java +++ b/src/newt/classes/com/jogamp/newt/Window.java @@ -45,6 +45,7 @@ import jogamp.newt.WindowImpl; import javax.media.nativewindow.CapabilitiesChooser; import javax.media.nativewindow.CapabilitiesImmutable; import javax.media.nativewindow.NativeWindow; +import javax.media.nativewindow.ScalableSurface; import javax.media.nativewindow.WindowClosingProtocol; import javax.media.nativewindow.util.Rectangle; import javax.media.nativewindow.util.RectangleImmutable; @@ -94,7 +95,7 @@ import javax.media.nativewindow.util.RectangleImmutable; * </pre> * </p> */ -public interface Window extends NativeWindow, WindowClosingProtocol { +public interface Window extends NativeWindow, WindowClosingProtocol, ScalableSurface { public static final boolean DEBUG_MOUSE_EVENT = Debug.debug("Window.MouseEvent"); public static final boolean DEBUG_KEY_EVENT = Debug.debug("Window.KeyEvent"); public static final boolean DEBUG_IMPLEMENTATION = Debug.debug("Window"); diff --git a/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java b/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java index 37e9f9813..baaa69e8e 100644 --- a/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java +++ b/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java @@ -865,6 +865,7 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto } newtChild.setVisible(false); newtChild.setSize(w, h); + jawtWindow.setSurfaceScale(newtChild.getSurfaceScale(new int[2])); newtChild.reparentWindow(jawtWindow, -1, -1, Window.REPARENT_HINT_BECOMES_VISIBLE); newtChild.addSurfaceUpdatedListener(jawtWindow); if( jawtWindow.isOffscreenLayerSurfaceEnabled() && diff --git a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java index a61085fb0..6610bd74f 100644 --- a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java +++ b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java @@ -404,6 +404,16 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind } @Override + public final void setSurfaceScale(final int[] pixelScale) { + window.setSurfaceScale(pixelScale); + } + + @Override + public final int[] getSurfaceScale(final int[] result) { + return window.getSurfaceScale(result); + } + + @Override public final void setPosition(int x, int y) { window.setPosition(x, y); } diff --git a/src/newt/classes/jogamp/newt/WindowImpl.java b/src/newt/classes/jogamp/newt/WindowImpl.java index 5288bfcc5..f02b9740d 100644 --- a/src/newt/classes/jogamp/newt/WindowImpl.java +++ b/src/newt/classes/jogamp/newt/WindowImpl.java @@ -48,6 +48,7 @@ import javax.media.nativewindow.NativeWindow; import javax.media.nativewindow.NativeWindowException; import javax.media.nativewindow.NativeWindowFactory; import javax.media.nativewindow.OffscreenLayerSurface; +import javax.media.nativewindow.ScalableSurface; import javax.media.nativewindow.SurfaceUpdatedListener; import javax.media.nativewindow.WindowClosingProtocol; import javax.media.nativewindow.util.DimensionImmutable; @@ -59,6 +60,7 @@ import javax.media.nativewindow.util.PointImmutable; import javax.media.nativewindow.util.Rectangle; import javax.media.nativewindow.util.RectangleImmutable; +import jogamp.nativewindow.SurfaceScaleUtils; import jogamp.nativewindow.SurfaceUpdatedHelper; import com.jogamp.common.util.ArrayHashSet; @@ -150,6 +152,9 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer private volatile boolean hasFocus = false; private volatile int pixWidth = 128, pixHeight = 128; // client-area size w/o insets in pixel units, default: may be overwritten by user private volatile int winWidth = 128, winHeight = 128; // client-area size w/o insets in window units, default: may be overwritten by user + protected int[] hasPixelScale = new int[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE }; + protected int[] reqPixelScale = new int[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE }; + 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) private boolean blockInsetsChange = false; // block insets change (from same thread) @@ -1953,9 +1958,25 @@ 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 int getPixelScaleX() { return 1; } + protected final int getPixelScaleX() { + return hasPixelScale[0]; + } + /** HiDPI: We currently base scaling of window units to pixel units on an integer scale factor per component. */ - protected int getPixelScaleY() { return 1; } + protected final int getPixelScaleY() { + return hasPixelScale[1]; + } + + @Override + public void setSurfaceScale(final int[] pixelScale) { + SurfaceScaleUtils.validateReqPixelScale(reqPixelScale, pixelScale, DEBUG_IMPLEMENTATION ? getClass().getSimpleName() : null); + } + + @Override + public final int[] getSurfaceScale(final int[] result) { + System.arraycopy(isNativeValid() ? hasPixelScale : reqPixelScale, 0, result, 0, 2); + return result; + } protected final boolean autoPosition() { return autoPosition; } diff --git a/src/newt/classes/jogamp/newt/driver/awt/AWTCanvas.java b/src/newt/classes/jogamp/newt/driver/awt/AWTCanvas.java index 5dab64e39..d01a2f21f 100644 --- a/src/newt/classes/jogamp/newt/driver/awt/AWTCanvas.java +++ b/src/newt/classes/jogamp/newt/driver/awt/AWTCanvas.java @@ -66,10 +66,16 @@ public class AWTCanvas extends Canvas { private volatile JAWTWindow jawtWindow=null; // the JAWTWindow presentation of this AWT Canvas, bound to the 'drawable' lifecycle private CapabilitiesChooser chooser=null; private final CapabilitiesImmutable capabilities; + private final UpstreamScalable upstreamScale; + + public static interface UpstreamScalable { + int[] getReqPixelScale(); + void setHasPixelScale(final int[] pixelScale); + } private boolean displayConfigChanged=false; - public AWTCanvas(CapabilitiesImmutable capabilities, CapabilitiesChooser chooser) { + public AWTCanvas(CapabilitiesImmutable capabilities, CapabilitiesChooser chooser, UpstreamScalable upstreamScale) { super(); if(null==capabilities) { @@ -77,6 +83,7 @@ public class AWTCanvas extends Canvas { } this.capabilities=capabilities; this.chooser=chooser; + this.upstreamScale = upstreamScale; } public AWTGraphicsConfiguration getAWTGraphicsConfiguration() { @@ -139,7 +146,9 @@ public class AWTCanvas extends Canvas { { jawtWindow = (JAWTWindow) NativeWindowFactory.getNativeWindow(this, awtConfig); // trigger initialization cycle + jawtWindow.setSurfaceScale( upstreamScale.getReqPixelScale() ); jawtWindow.lockSurface(); + upstreamScale.setHasPixelScale(jawtWindow.getSurfaceScale(new int[2])); jawtWindow.unlockSurface(); } @@ -152,10 +161,6 @@ public class AWTCanvas extends Canvas { } } - public int getPixelScale() { - final JAWTWindow _jawtWindow = jawtWindow; - return (null != _jawtWindow) ? _jawtWindow.getPixelScale() : 1; - } public NativeWindow getNativeWindow() { final JAWTWindow _jawtWindow = jawtWindow; return (null != _jawtWindow) ? _jawtWindow : null; diff --git a/src/newt/classes/jogamp/newt/driver/awt/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/awt/WindowDriver.java index cc92c4963..4064fdb05 100644 --- a/src/newt/classes/jogamp/newt/driver/awt/WindowDriver.java +++ b/src/newt/classes/jogamp/newt/driver/awt/WindowDriver.java @@ -98,16 +98,17 @@ public class WindowDriver extends WindowImpl { } } - @Override - protected final int getPixelScaleX() { - final AWTCanvas _awtCanvas = awtCanvas; - return null != _awtCanvas ? _awtCanvas.getPixelScale() : 1; - } + private final AWTCanvas.UpstreamScalable upstreamScalable = new AWTCanvas.UpstreamScalable() { + @Override + public int[] getReqPixelScale() { + return WindowDriver.this.reqPixelScale; + } - @Override - protected final int getPixelScaleY() { - return getPixelScaleX(); - } + @Override + public void setHasPixelScale(final int[] pixelScale) { + System.arraycopy(pixelScale, 0, WindowDriver.this.hasPixelScale, 0, 2); + } + }; @Override protected void createNativeImpl() { @@ -130,7 +131,7 @@ public class WindowDriver extends WindowImpl { awtContainer.setLayout(new BorderLayout()); if( null == awtCanvas ) { - awtCanvas = new AWTCanvas(capsRequested, WindowDriver.this.capabilitiesChooser); + awtCanvas = new AWTCanvas(capsRequested, WindowDriver.this.capabilitiesChooser, upstreamScalable); // canvas.addComponentListener(listener); awtContainer.add(awtCanvas, BorderLayout.CENTER); diff --git a/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java index cd852bb09..0fa4739a3 100644 --- a/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java +++ b/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java @@ -39,11 +39,13 @@ import javax.media.nativewindow.GraphicsConfigurationFactory; import javax.media.nativewindow.NativeWindow; import javax.media.nativewindow.NativeWindowException; import javax.media.nativewindow.MutableSurface; +import javax.media.nativewindow.ScalableSurface; import javax.media.nativewindow.VisualIDHolder; import javax.media.nativewindow.util.Insets; import javax.media.nativewindow.util.Point; import javax.media.nativewindow.util.PointImmutable; +import jogamp.nativewindow.SurfaceScaleUtils; import jogamp.nativewindow.macosx.OSXUtil; import jogamp.newt.PointerIconImpl; import jogamp.newt.ScreenImpl; @@ -62,43 +64,42 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl DisplayDriver.initSingleton(); } - private int pixelScale; - public WindowDriver() { - pixelScale = 1; } - private boolean updatePixelScale(final boolean sendEvent, final boolean defer, final float newPixelScaleRaw) { - final int newPixelScaleSafe = FloatUtil.isZero(newPixelScaleRaw, FloatUtil.EPSILON) ? 1 : (int) newPixelScaleRaw; - final boolean changed = pixelScale != newPixelScaleSafe; - if( DEBUG_IMPLEMENTATION ) { - System.err.println("WindowDriver.updatePixelScale.X: "+pixelScale+" -> "+newPixelScaleSafe+" (raw "+newPixelScaleRaw+") - changed "+changed); + private boolean updatePixelScale(final boolean sendEvent, final boolean defer, final float pixelScaleRaw) { + final int[] pixelScaleInt; + { + final int ps = FloatUtil.isZero(pixelScaleRaw, FloatUtil.EPSILON) ? 1 : (int) pixelScaleRaw; + pixelScaleInt = new int[] { ps, ps }; } - if( changed ) { - pixelScale = newPixelScaleSafe; + + if( SurfaceScaleUtils.computePixelScale(hasPixelScale, hasPixelScale, reqPixelScale, pixelScaleInt, DEBUG_IMPLEMENTATION ? getClass().getName() : null) ) { if( sendEvent ) { super.sizeChanged(defer, getWidth(), getHeight(), true); } else { defineSize(getWidth(), getHeight()); } + return true; + } else { + return false; } - return changed; } private boolean updatePixelScaleByScreenIdx(final boolean sendEvent) { final float newPixelScaleRaw = (float) OSXUtil.GetPixelScale(getScreen().getIndex()); if( DEBUG_IMPLEMENTATION ) { - System.err.println("WindowDriver.updatePixelScale.1: "+pixelScale+" -> "+newPixelScaleRaw); + System.err.println("WindowDriver.updatePixelScale.1: "+hasPixelScale[0]+" -> "+newPixelScaleRaw); } return updatePixelScale(sendEvent, true /* defer */, newPixelScaleRaw); } private boolean updatePixelScaleByWindowHandle(final boolean sendEvent) { - final long wh = getWindowHandle(); - if( 0 != wh ) { - final float newPixelScaleRaw = (float)OSXUtil.GetPixelScale(wh); + final long handle = getWindowHandle(); + if( 0 != handle ) { + final float newPixelScaleRaw = (float)OSXUtil.GetPixelScale(handle); if( DEBUG_IMPLEMENTATION ) { - System.err.println("WindowDriver.updatePixelScale.2: "+pixelScale+" -> "+newPixelScaleRaw); + System.err.println("WindowDriver.updatePixelScale.2: "+hasPixelScale[0]+" -> "+newPixelScaleRaw); } return updatePixelScale(sendEvent, true /* defer */, newPixelScaleRaw); } else { @@ -109,10 +110,10 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl /** Called from native code */ protected void updatePixelScale(final boolean defer, final float newPixelScaleRaw) { final long handle = getWindowHandle(); + if( DEBUG_IMPLEMENTATION ) { + System.err.println("WindowDriver.updatePixelScale.3: "+hasPixelScale[0]+" (has) -> "+newPixelScaleRaw+" (raw), drop "+(0==handle)); + } if( 0 != handle ) { - if( DEBUG_IMPLEMENTATION ) { - System.err.println("WindowDriver.updatePixelScale.3: "+pixelScale+" -> "+newPixelScaleRaw); - } updatePixelScale(true /* sendEvent*/, defer, newPixelScaleRaw); } } @@ -134,13 +135,43 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl } @Override - protected final int getPixelScaleX() { - return pixelScale; - } - - @Override - protected final int getPixelScaleY() { - return pixelScale; + public final void setSurfaceScale(final int[] pixelScale) { + SurfaceScaleUtils.validateReqPixelScale(reqPixelScale, pixelScale, DEBUG_IMPLEMENTATION ? getClass().getName() : null); + + final int[] resPixelScale; + if( isNativeValid() ) { + if( isOffscreenInstance ) { + final NativeWindow pWin = getParent(); + if( pWin instanceof ScalableSurface ) { + final ScalableSurface sSurf = (ScalableSurface)pWin; + sSurf.setSurfaceScale(reqPixelScale); + final int[] pPixelScale = sSurf.getSurfaceScale(new int[2]); + updatePixelScale(true /* sendEvent */, true /* defer */, pPixelScale[0]); // HiDPI: uniformPixelScale + } else { + // just notify updated pixelScale if offscreen + SurfaceScaleUtils.replaceAutoMaxWithPlatformMax(reqPixelScale); + updatePixelScale(true /* sendEvent */, true /* defer */, reqPixelScale[0]); // HiDPI: uniformPixelScale + } + } else { + // set pixelScale in native code, will issue an update PixelScale + OSXUtil.RunOnMainThread(true, new Runnable() { + @Override + public void run() { + setPixelScale0(getWindowHandle(), surfaceHandle, reqPixelScale[0]); // HiDPI: uniformPixelScale + } + } ); + } + 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()); + } } @Override @@ -351,6 +382,9 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl } } + final boolean setVisible = 0 != ( FLAG_IS_VISIBLE & flags); + final boolean hasFocus = hasFocus(); + if(DEBUG_IMPLEMENTATION) { final AbstractGraphicsConfiguration cWinCfg = this.getGraphicsConfiguration(); final NativeWindow pWin = getParent(); @@ -362,12 +396,10 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl ", isOffscreenInstance(sscSurfaceHandle "+toHexString(sscSurfaceHandle)+ ", ioi: "+_isOffscreenInstance+ ") -> "+isOffscreenInstance+ - "\n\t, "+getReconfigureFlagsAsString(null, flags)); + "\n\t, "+getReconfigureFlagsAsString(null, flags)+", setVisible "+setVisible+", hasFocus "+hasFocus); // Thread.dumpStack(); } - final boolean setVisible = 0 != ( FLAG_IS_VISIBLE & flags); - if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) && !setVisible ) { if ( !isOffscreenInstance ) { OSXUtil.RunOnMainThread(false, new Runnable() { @@ -395,6 +427,9 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl updatePixelScaleByWindowHandle(false /* sendEvent */); super.sizeChanged(false, width, height, true); visibleChanged(false, setVisible); + if( hasFocus ) { + requestFocusImpl(true); + } } else { if( width>0 && height>0 ) { if( !isOffscreenInstance ) { @@ -613,7 +648,7 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl if( 0 != surfaceHandle ) { throw new NativeWindowException("Internal Error - create w/o window, but has Newt NSView"); } - surfaceHandle = createView0(pS.getX(), pS.getY(), width, height, fullscreen); + surfaceHandle = createView0(pS.getX(), pS.getY(), width, height); if( 0 == surfaceHandle ) { throw new NativeWindowException("Could not create native view "+Thread.currentThread().getName()+" "+this); } @@ -633,7 +668,7 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl OSXUtil.RunOnMainThread(true, new Runnable() { @Override public void run() { - initWindow0( parentWinHandle, newWin, pS.getX(), pS.getY(), width, height, + initWindow0( parentWinHandle, newWin, pS.getX(), pS.getY(), width, height, reqPixelScale[0] /* HiDPI uniformPixelScale */, isOpaque, visible && !offscreenInstance, surfaceHandle); if( offscreenInstance ) { orderOut0(0!=parentWinHandle ? parentWinHandle : newWin); @@ -648,11 +683,12 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl } protected static native boolean initIDs0(); - private native long createView0(int x, int y, int w, int h, boolean fullscreen); + private native long createView0(int x, int y, int w, int h); private native long createWindow0(int x, int y, int w, int h, boolean fullscreen, int windowStyle, int backingStoreType, long view); /** Must be called on Main-Thread */ - private native void initWindow0(long parentWindow, long window, int x, int y, int w, int h, + private native void initWindow0(long parentWindow, long window, int x, int y, int w, int h, float reqPixelScale, boolean opaque, boolean visible, long view); + private native void setPixelScale0(long window, long view, float reqPixelScale); private native boolean lockSurface0(long window, long view); private native boolean unlockSurface0(long window, long view); /** Must be called on Main-Thread */ |