From 6516a52d3da5cced924db63b64af911d55355325 Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Tue, 27 Jan 2015 00:49:51 +0100 Subject: 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. --- .../classes/com/jogamp/newt/MonitorDevice.java | 48 ++++++++++++++++++---- src/newt/classes/com/jogamp/newt/Window.java | 2 +- .../classes/com/jogamp/newt/awt/NewtCanvasAWT.java | 42 +++++++++++++++---- .../classes/com/jogamp/newt/opengl/GLWindow.java | 17 +++++--- 4 files changed, 85 insertions(+), 24 deletions(-) (limited to 'src/newt/classes/com/jogamp') 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; * * *

@@ -65,16 +67,31 @@ public abstract class MonitorDevice { protected final ArrayHashSet 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 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 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,25 +197,39 @@ public abstract class MonitorDevice { } /** - * Returns the {@link RectangleImmutable rectangular} portion + * Returns the current {@link RectangleImmutable rectangular} portion * of the rotated 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 rotated 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 rotated 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 true if given screen coordinates in pixel units * are contained by this {@link #getViewport() viewport}, otherwise false. @@ -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 current {@link MonitorMode mode}'s * {@link SurfaceSize#getResolution() surface resolution}. *

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

      *    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
-- 
cgit v1.2.3