aboutsummaryrefslogtreecommitdiffstats
path: root/src/jogl/classes
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2015-01-27 00:49:51 +0100
committerSven Gothel <[email protected]>2015-01-27 00:49:51 +0100
commit6516a52d3da5cced924db63b64af911d55355325 (patch)
treefe4404bbd72d4db624722459c76a520019cfb4ca /src/jogl/classes
parent26f965bbe7b40968158901c3f4ef2f54e821ac70 (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.
Diffstat (limited to 'src/jogl/classes')
-rw-r--r--src/jogl/classes/javax/media/opengl/awt/GLCanvas.java103
-rw-r--r--src/jogl/classes/javax/media/opengl/awt/GLJPanel.java132
2 files changed, 159 insertions, 76 deletions
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++;
}