aboutsummaryrefslogtreecommitdiffstats
path: root/src/nativewindow/classes/jogamp
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2014-06-08 08:11:57 +0200
committerSven Gothel <[email protected]>2014-06-08 08:11:57 +0200
commit2571ed0b5ef14155d204540d38b564a7d4cd47b6 (patch)
tree8aaf1171af1b95f1cb1ebe706771a4aff3752c2f /src/nativewindow/classes/jogamp
parentff7bf3122fd2007bbe70cfadca9f0f978ee96456 (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/nativewindow/classes/jogamp')
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/SurfaceScaleUtils.java175
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/WrappedSurface.java59
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/jawt/macosx/MacOSXJAWTWindow.java26
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java18
4 files changed, 272 insertions, 6 deletions
diff --git a/src/nativewindow/classes/jogamp/nativewindow/SurfaceScaleUtils.java b/src/nativewindow/classes/jogamp/nativewindow/SurfaceScaleUtils.java
new file mode 100644
index 000000000..22e67ecff
--- /dev/null
+++ b/src/nativewindow/classes/jogamp/nativewindow/SurfaceScaleUtils.java
@@ -0,0 +1,175 @@
+/**
+ * Copyright 2014 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package jogamp.nativewindow;
+
+import javax.media.nativewindow.NativeWindowFactory;
+import javax.media.nativewindow.ScalableSurface;
+
+/**
+ * Basic {@link ScalableSurface} utility to validate and compute pixel-scale values.
+ */
+public class SurfaceScaleUtils {
+
+ private static final int[] PlatformMaxPixelScale;
+ private static final boolean PlatformUniformPixelScale;
+ private static final boolean PlatformPixelScaleSupported;
+
+ 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;
+ }
+ }
+
+ /**
+ * Compute a new valid pixelScale to be used by {@link NativeSurface} implementations,
+ * based on the given request and surface's pixelScale
+ *
+ * @param result int[2] storage for result, maybe same as <code>prePixelScale</code> for in-place
+ * @param prePixelScale previous pixelScale
+ * @param reqPixelScale requested pixelScale, validated via {@link #validateReqPixelScale(int[], int, String)}.
+ * @param surfPixelScaleRaw raw surface pixelScale
+ * @param DEBUG_PREFIX if set, dumps debug info on stderr using this prefix
+ * @return true if pixelScale has changed, otherwise false
+ */
+ public static boolean computePixelScale(int[] result, final int[] prePixelScale, final int[] reqPixelScale, final int[] surfPixelScaleRaw, final String DEBUG_PREFIX) {
+ final int surfPixelScaleSafeX = 0 < surfPixelScaleRaw[0] ? surfPixelScaleRaw[0] : ScalableSurface.IDENTITY_PIXELSCALE;
+ final int surfPixelScaleSafeY = 0 < surfPixelScaleRaw[1] ? surfPixelScaleRaw[1] : ScalableSurface.IDENTITY_PIXELSCALE;
+ final boolean useHiDPI = ScalableSurface.IDENTITY_PIXELSCALE != reqPixelScale[0] || ScalableSurface.IDENTITY_PIXELSCALE != reqPixelScale[1];
+ final int prePixelScaleX = prePixelScale[0];
+ final int prePixelScaleY = prePixelScale[1];
+
+ if( useHiDPI ) {
+ result[0] = surfPixelScaleSafeX;
+ result[1] = surfPixelScaleSafeY;
+ } else {
+ result[0] = ScalableSurface.IDENTITY_PIXELSCALE;
+ result[1] = ScalableSurface.IDENTITY_PIXELSCALE;
+ }
+
+ if( result[0] != prePixelScaleX || result[1] != prePixelScaleY ) {
+ if( null != DEBUG_PREFIX ) {
+ System.err.println(DEBUG_PREFIX+".computePixelScale: useHiDPI "+useHiDPI+", ["+prePixelScaleX+"x"+prePixelScaleY+" (pre), "+
+ reqPixelScale[0]+"x"+reqPixelScale[1]+" (req)] -> "+
+ surfPixelScaleRaw[0]+"x"+surfPixelScaleRaw[1]+" (raw) -> "+
+ surfPixelScaleSafeX+"x"+surfPixelScaleSafeY+" (safe) -> "+
+ result[0]+"x"+result[1]+" (use)");
+ }
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * 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>
+ *
+ * @param result int[2] storage for result
+ * @param reqPixelScale requested pixelScale
+ * @param DEBUG_PREFIX if set, dumps debug info on stderr using this prefix
+ */
+ 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)");
+ }
+ }
+
+ /**
+ * Replaces {@link ScalableSurface#AUTOMAX_PIXELSCALE} with {@link #getPlatformMaxPixelScale(int[])},
+ * for each component.
+ *
+ * @param pixelScale int[2] value array to be tested and replaced
+ */
+ 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];
+ }
+ }
+
+ /**
+ * Returns the maximum platform pixelScale
+ */
+ public static int[] getPlatformMaxPixelScale(final int[] result) {
+ System.arraycopy(PlatformMaxPixelScale, 0, result, 0, 2);
+ return result;
+ }
+
+ /**
+ * Returns true if platform pixelScale is uniform, i.e. same scale factor for x- and y-direction, otherwise false.
+ */
+ public static boolean isPlatformPixelScaleUniform() {
+ return PlatformUniformPixelScale;
+ }
+
+ /**
+ * Returns whether the platform supports pixelScale
+ */
+ public static boolean isPlatformPixelScaleSupported() {
+ return PlatformPixelScaleSupported;
+ }
+
+}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/WrappedSurface.java b/src/nativewindow/classes/jogamp/nativewindow/WrappedSurface.java
index 902223c80..1a8772988 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/WrappedSurface.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/WrappedSurface.java
@@ -31,6 +31,7 @@ package jogamp.nativewindow;
import javax.media.nativewindow.AbstractGraphicsConfiguration;
import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.ProxySurface;
+import javax.media.nativewindow.ScalableSurface;
import javax.media.nativewindow.UpstreamSurfaceHook;
import com.jogamp.nativewindow.UpstreamSurfaceHookMutableSize;
@@ -40,8 +41,9 @@ import com.jogamp.nativewindow.UpstreamSurfaceHookMutableSize;
*
* @see ProxySurface
*/
-public class WrappedSurface extends ProxySurfaceImpl {
- protected long surfaceHandle;
+public class WrappedSurface extends ProxySurfaceImpl implements ScalableSurface {
+ private final int[] hasPixelScale = new int[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE };
+ private long surfaceHandle;
/**
* Utilizes a {@link UpstreamSurfaceHook.MutableSize} to hold the size information,
@@ -76,6 +78,8 @@ public class WrappedSurface extends ProxySurfaceImpl {
@Override
protected void invalidateImpl() {
surfaceHandle = 0;
+ hasPixelScale[0] = ScalableSurface.IDENTITY_PIXELSCALE;
+ hasPixelScale[1] = ScalableSurface.IDENTITY_PIXELSCALE;
}
@Override
@@ -97,14 +101,61 @@ public class WrappedSurface extends ProxySurfaceImpl {
protected final void unlockSurfaceImpl() {
}
+ /**
+ * {@inheritDoc}
+ * <p>
+ * {@link WrappedSurface}'s implementation uses the {@link #setSurfaceScale(int[]) given pixelScale} directly.
+ * </p>
+ */
@Override
public final int[] convertToWindowUnits(final int[] pixelUnitsAndResult) {
- return pixelUnitsAndResult; // FIXME HiDPI: use 'pixelScale'
+ pixelUnitsAndResult[0] /= hasPixelScale[0];
+ pixelUnitsAndResult[1] /= hasPixelScale[1];
+ return pixelUnitsAndResult;
}
+ /**
+ * {@inheritDoc}
+ * <p>
+ * {@link WrappedSurface}'s implementation uses the {@link #setSurfaceScale(int[]) given pixelScale} directly.
+ * </p>
+ */
@Override
public final int[] convertToPixelUnits(final int[] windowUnitsAndResult) {
- return windowUnitsAndResult; // FIXME HiDPI: use 'pixelScale'
+ windowUnitsAndResult[0] *= hasPixelScale[0];
+ windowUnitsAndResult[1] *= hasPixelScale[1];
+ return windowUnitsAndResult;
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p>
+ * {@link WrappedSurface}'s implementation is to simply pass the given pixelScale
+ * from the caller <i>down</i> to this instance without validation to be applied in the {@link #convertToPixelUnits(int[]) conversion} {@link #convertToWindowUnits(int[]) methods} <b>only</b>.<br/>
+ * This allows the caller to pass down knowledge about window- and pixel-unit conversion and utilize mentioned conversion methods.
+ * </p>
+ * <p>
+ * The given pixelScale will not impact the actual {@link #getSurfaceWidth()} and {@link #getSurfaceHeight()},
+ * which is determinated by this instances {@link #getUpstreamSurface() upstream surface}.
+ * </p>
+ * <p>
+ * Implementation uses the default pixelScale {@link ScalableSurface#IDENTITY_PIXELSCALE}
+ * and resets to default values on {@link #invalidateImpl()}, i.e. {@link #destroyNotify()}.
+ * </p>
+ * <p>
+ * Implementation returns the given pixelScale array.
+ * </p>
+ */
+ @Override
+ public final void setSurfaceScale(final int[] pixelScale) {
+ hasPixelScale[0] = pixelScale[0];
+ hasPixelScale[1] = pixelScale[1];
+ }
+
+ @Override
+ public final int[] getSurfaceScale(final int[] result) {
+ System.arraycopy(hasPixelScale, 0, result, 0, 2);
+ return result;
}
} \ No newline at end of file
diff --git a/src/nativewindow/classes/jogamp/nativewindow/jawt/macosx/MacOSXJAWTWindow.java b/src/nativewindow/classes/jogamp/nativewindow/jawt/macosx/MacOSXJAWTWindow.java
index 3b91fc8ab..3d88049b2 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/jawt/macosx/MacOSXJAWTWindow.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/jawt/macosx/MacOSXJAWTWindow.java
@@ -114,6 +114,27 @@ public class MacOSXJAWTWindow extends JAWTWindow implements MutableSurface {
}
@Override
+ public void setSurfaceScale(final int[] pixelScale) {
+ super.setSurfaceScale(pixelScale);
+ if( 0 != drawable ) { // locked at least once !
+ final int hadPixelScaleX = getPixelScaleX();
+ updatePixelScale();
+
+ if( hadPixelScaleX != getPixelScaleX() && 0 != getAttachedSurfaceLayer() ) {
+ OSXUtil.RunOnMainThread(false, new Runnable() {
+ @Override
+ public void run() {
+ final long osl = getAttachedSurfaceLayer();
+ if( 0 != osl ) {
+ OSXUtil.SetCALayerPixelScale(rootSurfaceLayer, osl, getPixelScaleX());
+ }
+ }
+ });
+ }
+ }
+ }
+
+ @Override
protected void attachSurfaceLayerImpl(final long layerHandle) {
OSXUtil.RunOnMainThread(false, new Runnable() {
@Override
@@ -143,7 +164,8 @@ public class MacOSXJAWTWindow extends JAWTWindow implements MutableSurface {
} else if( DEBUG ) {
System.err.println("JAWTWindow.attachSurfaceLayerImpl: "+toHexString(layerHandle) + ", [ins "+outterInsets+"], p0 "+p0+" -> "+p1+", bounds "+bounds);
}
- OSXUtil.AddCASublayer(rootSurfaceLayer, layerHandle, p1.getX(), p1.getY(), getWidth(), getHeight(), getPixelScale(), JAWTUtil.getOSXCALayerQuirks());
+ // HiDPI: uniform pixel scale
+ OSXUtil.AddCASublayer(rootSurfaceLayer, layerHandle, p1.getX(), p1.getY(), getWidth(), getHeight(), getPixelScaleX(), JAWTUtil.getOSXCALayerQuirks());
} } );
}
@@ -309,7 +331,7 @@ public class MacOSXJAWTWindow extends JAWTWindow implements MutableSurface {
public void run() {
String errMsg = null;
if(0 == rootSurfaceLayer && 0 != jawtSurfaceLayersHandle) {
- rootSurfaceLayer = OSXUtil.CreateCALayer(bounds.getWidth(), bounds.getHeight(), getPixelScale());
+ rootSurfaceLayer = OSXUtil.CreateCALayer(bounds.getWidth(), bounds.getHeight(), getPixelScaleX()); // HiDPI: uniform pixel scale
if(0 == rootSurfaceLayer) {
errMsg = "Could not create root CALayer";
} else {
diff --git a/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java b/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java
index 12e574ced..a91698f62 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java
@@ -44,6 +44,9 @@ public class OSXUtil implements ToolkitProperties {
private static boolean isInit = false;
private static final boolean DEBUG = Debug.debug("OSXUtil");
+ /** FIXME HiDPI: OSX unique and maximum value {@value} */
+ public static final int MAX_PIXELSCALE = 2;
+
/**
* Called by {@link NativeWindowFactory#initSingleton()}
* @see ToolkitProperties
@@ -201,6 +204,20 @@ public class OSXUtil implements ToolkitProperties {
}
/**
+ * Set root and sub CALayer pixelScale / contentScale for HiDPI
+ *
+ * @param rootCALayer the root surface layer, maybe null.
+ * @param subCALayer the client surface layer, maybe null.
+ * @param contentsScale scale for HiDPI support: pixel-dim = window-dim x scale
+ */
+ public static void SetCALayerPixelScale(final long rootCALayer, final long subCALayer, final float contentsScale) {
+ if( 0==rootCALayer && 0==subCALayer ) {
+ return;
+ }
+ SetCALayerPixelScale0(rootCALayer, subCALayer, contentsScale);
+ }
+
+ /**
* Detach a sub CALayer from the root CALayer.
*/
public static void RemoveCASublayer(final long rootCALayer, final long subCALayer) {
@@ -364,6 +381,7 @@ public class OSXUtil implements ToolkitProperties {
private static native long CreateCALayer0(int width, int height, float contentsScale);
private static native void AddCASublayer0(long rootCALayer, long subCALayer, int x, int y, int width, int height, float contentsScale, int caLayerQuirks);
private static native void FixCALayerLayout0(long rootCALayer, long subCALayer, boolean visible, int x, int y, int width, int height, int caLayerQuirks);
+ private static native void SetCALayerPixelScale0(long rootCALayer, long subCALayer, float contentsScale);
private static native void RemoveCASublayer0(long rootCALayer, long subCALayer);
private static native void DestroyCALayer0(long caLayer);
private static native void RunOnMainThread0(Runnable runnable);