diff options
author | Sven Gothel <[email protected]> | 2014-07-27 23:23:15 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2014-07-27 23:23:15 +0200 |
commit | 15b9e36e80d6f62f7dfb5c45d00cd04de2007ee5 (patch) | |
tree | ee7b7e78e47ed9d2ea504b7232825b1d13a71071 | |
parent | 007f120cd8d33e4231ef4d207b85ed156d1e0c82 (diff) |
Bug 1035 - Allow Gamma [Brightness, Contrast] settings to be performed on display/screen of a NativeSurface
Currently GLDrawableFactoryImpl's gamma settings are performed
only on the main screen.
Allow passing a NativeSurface, so it's display/screen
gamma values will be changed.
Further, promote low-level gamma settings to GLDrawableFactory
for direct usage.
Change com.jogamp.opengl.util.Gamma to use a GLDrawable
instead of a GL object to clarify that we use the drawable.
Also add a GLAutoDrawable variant, allowing proper locking
of its 'upstream-lock' to guarantee atomicity.
+++
Tested manually w/ TestGearsES2NEWT on X11 and Windows
using the 'g' and 'G' to modify gamma.
Value is properly reset on exit.
9 files changed, 404 insertions, 175 deletions
diff --git a/make/scripts/tests-win.bat b/make/scripts/tests-win.bat index 4161b534c..d4e10e889 100755 --- a/make/scripts/tests-win.bat +++ b/make/scripts/tests-win.bat @@ -2,12 +2,12 @@ REM scripts\java-win.bat jogamp.newt.awt.opengl.VersionApplet REM scripts\java-win.bat com.jogamp.newt.opengl.GLWindow REM scripts\java-win.bat javax.media.opengl.awt.GLCanvas REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.acore.TestMainVersionGLWindowNEWT %* -scripts\java-win.bat com.jogamp.oculusvr.OVRVersion %* +REM scripts\java-win.bat com.jogamp.oculusvr.OVRVersion %* REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.demos.gl2.newt.TestGearsNewtAWTWrapper %* REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.demos.gl2.newt.TestGearsNEWT -time 30000 REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.demos.es1.newt.TestGearsES1NEWT %* -REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NEWT %* +scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NEWT %* REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NEWT -vsync -time 4000 -x 10 -y 10 -width 100 -height 100 -screen 0 REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NEWT -vsync -time 40000 -width 100 -height 100 -screen 0 %* REM scripts\java-win.bat com.jogamp.opengl.test.junit.jogl.demos.gl2.awt.TestGearsAWT -time 5000 diff --git a/make/scripts/tests.sh b/make/scripts/tests.sh index 886d7c234..48538c2ee 100644 --- a/make/scripts/tests.sh +++ b/make/scripts/tests.sh @@ -399,7 +399,7 @@ function testawtswt() { #testawt com.jogamp.opengl.test.junit.jogl.demos.es2.awt.TestGearsES2GLJPanelsAWT $* #testawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NewtCanvasAWT $* #testawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestLandscapeES2NewtCanvasAWT $* -#testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NEWT $* +testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NEWT $* #testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestLandscapeES2NEWT $* #testawtswt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NewtCanvasSWT $* #testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestElektronenMultipliziererNEWT $* @@ -533,7 +533,7 @@ function testawtswt() { #testnoawt com.jogamp.opengl.test.junit.jogl.acore.glels.TestGLContextDrawableSwitch01NEWT $* #testnoawt com.jogamp.opengl.test.junit.jogl.acore.glels.TestGLContextDrawableSwitch10NEWT $* #testawt com.jogamp.opengl.test.junit.jogl.acore.glels.TestGLContextDrawableSwitch11NewtAWT $* -testawt com.jogamp.opengl.test.junit.jogl.acore.glels.TestGLContextDrawableSwitch12AWT $* +#testawt com.jogamp.opengl.test.junit.jogl.acore.glels.TestGLContextDrawableSwitch12AWT $* #testawt com.jogamp.opengl.test.junit.jogl.acore.glels.TestGLContextDrawableSwitch21Newt2AWT $* #testawt com.jogamp.opengl.test.junit.jogl.acore.glels.TestBug722GLContextDrawableSwitchNewt2AWT $* diff --git a/src/jogl/classes/com/jogamp/opengl/util/Gamma.java b/src/jogl/classes/com/jogamp/opengl/util/Gamma.java index 4e44c997a..bab85e531 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/Gamma.java +++ b/src/jogl/classes/com/jogamp/opengl/util/Gamma.java @@ -39,69 +39,79 @@ package com.jogamp.opengl.util; -import javax.media.opengl.*; -import jogamp.opengl.*; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLDrawable; +import javax.media.opengl.GLDrawableFactory; -/** Provides control over the primary display's gamma, brightness and - contrast controls via the hardware gamma ramp tables. Not - supported on all platforms or graphics hardware. <P> - - Thanks to the LWJGL project for illustrating how to access gamma - control on the various platforms. -*/ +import com.jogamp.common.util.locks.RecursiveLock; +/** + * Provides convenient wrapper for {@link GLDrawableFactory} control over + * individual display's gamma, brightness and contrast values + * via the hardware gamma ramp tables. + * <p> + * Not supported on all platforms or graphics hardware. + * </p> + * <p> + * Thanks to the LWJGL project for illustrating how to access gamma + * control on the various platforms. + * </p> + */ public class Gamma { private Gamma() {} /** - * Sets the gamma, brightness, and contrast of the current main - * display. This functionality is not available on all platforms and - * graphics hardware. Returns true if the settings were successfully - * changed, false if not. This method may return false for some - * values of the incoming arguments even on hardware which does - * support the underlying functionality. <P> - * - * If this method returns true, the display settings will - * automatically be reset to their original values upon JVM exit - * (assuming the JVM does not crash); if the user wishes to change - * the display settings back to normal ahead of time, use {@link - * #resetDisplayGamma resetDisplayGamma}(). It is recommended to - * call {@link #resetDisplayGamma resetDisplayGamma} before calling - * e.g. <code>System.exit()</code> from the application rather than - * rely on the shutdown hook functionality due to inevitable race - * conditions and unspecified behavior during JVM teardown. <P> - * - * This method may be called multiple times during the application's - * execution, but calling {@link #resetDisplayGamma - * resetDisplayGamma} will only reset the settings to the values - * before the first call to this method. <P> - * - * @param gamma The gamma value, typically > 1.0 (default values - * vary, but typically roughly 1.0) - * @param brightness The brightness value between -1.0 and 1.0, - * inclusive (default values vary, but typically 0) - * @param contrast The contrast, greater than 0.0 (default values - * vary, but typically 1) - * @return true if gamma settings were successfully changed, false - * if not - * @throws IllegalArgumentException if any of the parameters were - * out-of-bounds + * Convenient wrapper for {@link GLDrawableFactory#setDisplayGamma(javax.media.nativewindow.NativeSurface, float, float, float)}. + * <p> + * Use {@link #setDisplayGamma(GLAutoDrawable, float, float, float)} in case of using an {#link GLAutoDrawable}. + * </p> + */ + public static boolean setDisplayGamma(final GLDrawable drawable, final float gamma, final float brightness, final float contrast) throws IllegalArgumentException { + return GLDrawableFactory.getFactory(drawable.getGLProfile()).setDisplayGamma(drawable.getNativeSurface(), gamma, brightness, contrast); + } + + /** + * Convenient wrapper for {@link GLDrawableFactory#setDisplayGamma(javax.media.nativewindow.NativeSurface, float, float, float)} + * locking {@link GLAutoDrawable#getUpstreamLock()} to ensure proper atomic operation. + */ + public static boolean setDisplayGamma(final GLAutoDrawable drawable, final float gamma, final float brightness, final float contrast) throws IllegalArgumentException { + final RecursiveLock lock = drawable.getUpstreamLock(); + lock.lock(); + try { + return GLDrawableFactory.getFactory(drawable.getGLProfile()).setDisplayGamma(drawable.getNativeSurface(), gamma, brightness, contrast); + } finally { + lock.unlock(); + } + } + + /** + * Convenient wrapper for {@link GLDrawableFactory#resetDisplayGamma(javax.media.nativewindow.NativeSurface)}. + * <p> + * Use {@link #resetDisplayGamma(GLAutoDrawable)} in case of using an {#link GLAutoDrawable}. + * </p> + */ + public static void resetDisplayGamma(final GLDrawable drawable) { + GLDrawableFactory.getFactory(drawable.getGLProfile()).resetDisplayGamma(drawable.getNativeSurface()); + } + + /** + * Convenient wrapper for {@link GLDrawableFactory#resetDisplayGamma(javax.media.nativewindow.NativeSurface)} + * locking {@link GLAutoDrawable#getUpstreamLock()} to ensure proper atomic operation. */ - public static boolean setDisplayGamma(final GL gl, final float gamma, final float brightness, final float contrast) throws IllegalArgumentException { - return GLDrawableFactoryImpl.getFactoryImpl(gl.getContext().getGLDrawable().getGLProfile()).setDisplayGamma(gamma, brightness, contrast); + public static void resetDisplayGamma(final GLAutoDrawable drawable) { + final RecursiveLock lock = drawable.getUpstreamLock(); + lock.lock(); + try { + GLDrawableFactory.getFactory(drawable.getGLProfile()).resetDisplayGamma(drawable.getNativeSurface()); + } finally { + lock.unlock(); + } } /** - * Resets the gamma, brightness and contrast values for the primary - * display to their original values before {@link #setDisplayGamma - * setDisplayGamma} was called the first time. {@link - * #setDisplayGamma setDisplayGamma} must be called before calling - * this method or an unspecified exception will be thrown. While it - * is not explicitly required that this method be called before - * exiting, calling it is recommended because of the inevitable - * unspecified behavior during JVM teardown. + * Convenient wrapper for {@link GLDrawableFactory#resetAllDisplayGamma()}. */ - public static void resetDisplayGamma(final GL gl) { - GLDrawableFactoryImpl.getFactoryImpl(gl.getContext().getGLDrawable().getGLProfile()).resetDisplayGamma(); + public static void resetAllDisplayGamma(final GLDrawable drawable) { + GLDrawableFactory.getFactory(drawable.getGLProfile()).resetAllDisplayGamma(); } } diff --git a/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java b/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java index 82808a3cb..c11195c58 100644 --- a/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java +++ b/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java @@ -222,7 +222,7 @@ public abstract class GLDrawableFactory { System.err.println("GLDrawableFactory.shutdownAll["+(i+1)+"/"+gldfCount+"]: "+gldf.getClass().getName()); } try { - gldf.resetDisplayGamma(); + gldf.resetAllDisplayGammaNoSync(); gldf.shutdownImpl(); } catch (final Throwable t) { System.err.println("GLDrawableFactory.shutdownImpl: Caught "+t.getClass().getName()+" during factory shutdown #"+(i+1)+"/"+gldfCount+" "+gldf.getClass().getName()); @@ -259,7 +259,70 @@ public abstract class GLDrawableFactory { protected abstract void shutdownImpl(); - public abstract void resetDisplayGamma(); + /** + * Sets the gamma, brightness, and contrast of the display associated with the given <code>surface</code>. + * <p> + * This functionality is not available on all platforms and + * graphics hardware. Returns true if the settings were successfully + * changed, false if not. This method may return false for some + * values of the incoming arguments even on hardware which does + * support the underlying functionality. </p> + * <p> + * If this method returns true, the display settings will + * automatically be reset to their original values upon JVM exit + * (assuming the JVM does not crash); if the user wishes to change + * the display settings back to normal ahead of time, + * use {@link #resetDisplayGamma(NativeSurface)} or {@link #resetAllDisplayGamma()}. + * </p> + * <p> + * It is recommended to call {@link #resetDisplayGamma(NativeSurface)} or {@link #resetAllDisplayGamma()} + * before calling e.g. <code>System.exit()</code> from the application rather than + * rely on the shutdown hook functionality due to inevitable race + * conditions and unspecified behavior during JVM teardown. + * </p> + * <p> + * This method may be called multiple times during the application's + * execution, but calling {@link #resetDisplayGamma(NativeSurface)} + * will only reset the settings to the values + * before the first call to this method. </p> + * + * @param surface denominates the display device + * @param gamma The gamma value, typically > 1.0 (default values vary, but typically roughly 1.0) + * @param brightness The brightness value between -1.0 and 1.0, inclusive (default values vary, but typically 0) + * @param contrast The contrast, greater than 0.0 (default values vary, but typically 1) + * + * @return true if gamma settings were successfully changed, false if not + * @throws IllegalArgumentException if any of the parameters were out-of-bounds + * @see #resetDisplayGamma(NativeSurface) + * @see #resetAllDisplayGamma() + */ + public abstract boolean setDisplayGamma(final NativeSurface surface, final float gamma, final float brightness, final float contrast) throws IllegalArgumentException; + + /** + * Resets the gamma, brightness and contrast values of the display associated with the given <code>surface</code> + * to its original values before {@link #setDisplayGamma(NativeSurface, float, float, float) setDisplayGamma} + * was called the first time. + * <p> + * While it is not explicitly required that this method be called before + * exiting manually, calling it is recommended because of the inevitable + * unspecified behavior during JVM teardown. + * </p> + */ + public abstract void resetDisplayGamma(final NativeSurface surface); + + /** + * Resets the gamma, brightness and contrast values of all modified + * displays to their original values before {@link #setDisplayGamma(NativeSurface, float, float, float) setDisplayGamma} + * was called the first time. + * <p> + * While it is not explicitly required that this method be called before + * exiting manually, calling it is recommended because of the inevitable + * unspecified behavior during JVM teardown. + * </p> + */ + public abstract void resetAllDisplayGamma(); + + protected abstract void resetAllDisplayGammaNoSync(); /** * Retrieve the default <code>device</code> {@link AbstractGraphicsDevice#getConnection() connection}, diff --git a/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java b/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java index 0b119b50d..8d65f16d3 100644 --- a/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java +++ b/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java @@ -41,8 +41,14 @@ package jogamp.opengl; import java.nio.Buffer; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; +import javax.media.nativewindow.AbstractGraphicsConfiguration; import javax.media.nativewindow.AbstractGraphicsDevice; +import javax.media.nativewindow.AbstractGraphicsScreen; import javax.media.nativewindow.NativeSurface; import javax.media.nativewindow.NativeWindowFactory; import javax.media.nativewindow.OffscreenLayerSurface; @@ -516,64 +522,98 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - /** - * Sets the gamma, brightness, and contrast of the current main - * display. Returns true if the settings were changed, false if - * not. If this method returns true, the display settings will - * automatically be reset upon JVM exit (assuming the JVM does not - * crash); if the user wishes to change the display settings back to - * normal ahead of time, use resetDisplayGamma(). Throws - * IllegalArgumentException if any of the parameters were - * out-of-bounds. - * - * @param gamma The gamma value, typically > 1.0 (default value is - * 1.0) - * @param brightness The brightness value between -1.0 and 1.0, - * inclusive (default value is 0) - * @param contrast The contrast, greater than 0.0 (default value is 1) - * @throws IllegalArgumentException if any of the parameters were - * out-of-bounds - */ - public boolean setDisplayGamma(final float gamma, final float brightness, final float contrast) throws IllegalArgumentException { + @Override + public synchronized final boolean setDisplayGamma(final NativeSurface surface, final float gamma, final float brightness, final float contrast) throws IllegalArgumentException { if ((brightness < -1.0f) || (brightness > 1.0f)) { throw new IllegalArgumentException("Brightness must be between -1.0 and 1.0"); } if (contrast < 0) { throw new IllegalArgumentException("Contrast must be greater than 0.0"); } - // FIXME: ensure gamma is > 1.0? Are smaller / negative values legal? - final int rampLength = getGammaRampLength(); - if (rampLength == 0) { - return false; + if( NativeSurface.LOCK_SURFACE_NOT_READY >= surface.lockSurface() ) { + return false; + } + try { + // FIXME: ensure gamma is > 1.0? Are smaller / negative values legal? + final int rampLength = getGammaRampLength(surface); + if (rampLength == 0) { + return false; + } + final float[] gammaRamp = new float[rampLength]; + for (int i = 0; i < rampLength; i++) { + final float intensity = (float) i / (float) (rampLength - 1); + // apply gamma + float rampEntry = (float) java.lang.Math.pow(intensity, gamma); + // apply brightness + rampEntry += brightness; + // apply contrast + rampEntry = (rampEntry - 0.5f) * contrast + 0.5f; + // Clamp entry to [0, 1] + if (rampEntry > 1.0f) + rampEntry = 1.0f; + else if (rampEntry < 0.0f) + rampEntry = 0.0f; + gammaRamp[i] = rampEntry; + } + final AbstractGraphicsScreen screen = surface.getGraphicsConfiguration().getScreen(); + final DeviceScreenID deviceScreenID = new DeviceScreenID(screen.getDevice().getConnection(), screen.getIndex()); + if( null == screen2OrigGammaRamp.get(deviceScreenID) ) { + screen2OrigGammaRamp.put(deviceScreenID, getGammaRamp(surface)); // cache original gamma ramp once + if( DEBUG ) { + System.err.println("DisplayGamma: Stored: "+deviceScreenID); + dumpGammaStore(); + } + } + return setGammaRamp(surface, gammaRamp); + } finally { + surface.unlockSurface(); } - final float[] gammaRamp = new float[rampLength]; - for (int i = 0; i < rampLength; i++) { - final float intensity = (float) i / (float) (rampLength - 1); - // apply gamma - float rampEntry = (float) java.lang.Math.pow(intensity, gamma); - // apply brightness - rampEntry += brightness; - // apply contrast - rampEntry = (rampEntry - 0.5f) * contrast + 0.5f; - // Clamp entry to [0, 1] - if (rampEntry > 1.0f) - rampEntry = 1.0f; - else if (rampEntry < 0.0f) - rampEntry = 0.0f; - gammaRamp[i] = rampEntry; + } + + @Override + public synchronized final void resetDisplayGamma(final NativeSurface surface) { + if( NativeSurface.LOCK_SURFACE_NOT_READY >= surface.lockSurface() ) { + return; } - if( !needsGammaRampReset ) { - originalGammaRamp = getGammaRamp(); - needsGammaRampReset = true; + try { + final AbstractGraphicsScreen screen = surface.getGraphicsConfiguration().getScreen(); + final DeviceScreenID deviceScreenID = new DeviceScreenID(screen.getDevice().getConnection(), screen.getIndex()); + final Buffer originalGammaRamp = screen2OrigGammaRamp.remove(deviceScreenID); + if( null != originalGammaRamp ) { + resetGammaRamp(surface, originalGammaRamp); + } + } finally { + surface.unlockSurface(); } - return setGammaRamp(gammaRamp); } @Override - public synchronized void resetDisplayGamma() { - if( needsGammaRampReset ) { - resetGammaRamp(originalGammaRamp); - needsGammaRampReset = false; + public synchronized final void resetAllDisplayGamma() { + resetAllDisplayGammaNoSync(); + } + + @Override + protected final void resetAllDisplayGammaNoSync() { + if( DEBUG ) { + System.err.println("DisplayGamma: Reset"); + dumpGammaStore(); + } + final Set<DeviceScreenID> deviceScreenIDs = screen2OrigGammaRamp.keySet(); + for( final Iterator<DeviceScreenID> i = deviceScreenIDs.iterator(); i.hasNext(); ) { + final DeviceScreenID deviceScreenID = i.next(); + final Buffer originalGammaRamp = screen2OrigGammaRamp.remove(deviceScreenID); + if( null != originalGammaRamp ) { + resetGammaRamp(deviceScreenID, originalGammaRamp); + } + } + } + private void dumpGammaStore() { + final Set<DeviceScreenID> deviceScreenIDs = screen2OrigGammaRamp.keySet(); + int count = 0; + for( final Iterator<DeviceScreenID> i = deviceScreenIDs.iterator(); i.hasNext(); count++) { + final DeviceScreenID deviceScreenID = i.next(); + final Buffer originalGammaRamp = screen2OrigGammaRamp.get(deviceScreenID); + System.err.printf("%4d/%4d: %s -> %s%n", count, deviceScreenIDs.size(), deviceScreenID, originalGammaRamp); } } @@ -582,30 +622,64 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { // /** Returns the length of the computed gamma ramp for this OS and - hardware. Returns 0 if gamma changes are not supported. */ - protected int getGammaRampLength() { + hardware. Returns 0 if gamma changes are not supported. + * @param surface TODO*/ + protected int getGammaRampLength(final NativeSurface surface) { return 0; } /** Sets the gamma ramp for the main screen. Returns false if gamma - ramp changes were not supported. */ - protected boolean setGammaRamp(final float[] ramp) { + ramp changes were not supported. + * @param surface TODO*/ + protected boolean setGammaRamp(final NativeSurface surface, final float[] ramp) { return false; } /** Gets the current gamma ramp. This is basically an opaque value used only on some platforms to reset the gamma ramp to its - original settings. */ - protected Buffer getGammaRamp() { + original settings. + * @param surface TODO*/ + protected Buffer getGammaRamp(final NativeSurface surface) { return null; } /** Resets the gamma ramp, potentially using the specified Buffer as - data to restore the original values. */ - protected void resetGammaRamp(final Buffer originalGammaRamp) { + data to restore the original values. + * @param surface TODO*/ + protected void resetGammaRamp(final NativeSurface surface, final Buffer originalGammaRamp) { + } + protected void resetGammaRamp(final DeviceScreenID deviceScreenID, final Buffer originalGammaRamp) { } // Shutdown hook mechanism for resetting gamma - private volatile Buffer originalGammaRamp; - private volatile boolean needsGammaRampReset = false; + public final class DeviceScreenID { + public final String deviceConnection; + public final int screenIdx; + DeviceScreenID(final String deviceConnection, final int screenIdx) { + this.deviceConnection = deviceConnection; + this.screenIdx = screenIdx; + } + @Override + public int hashCode() { + // 31 * x == (x << 5) - x + int hash = 31 + deviceConnection.hashCode(); + hash = ((hash << 5) - hash) + screenIdx; + return hash; + } + @Override + public boolean equals(final Object obj) { + if(this == obj) { return true; } + if (obj instanceof DeviceScreenID) { + final DeviceScreenID other = (DeviceScreenID)obj; + return this.deviceConnection.equals(other.deviceConnection) && + this.screenIdx == other.screenIdx; + } + return false; + } + @Override + public String toString() { + return "DeviceScreenID[devCon "+deviceConnection+", screenIdx "+screenIdx+", hash 0x"+Integer.toHexString(hashCode())+"]"; + } + } + private final Map<DeviceScreenID, Buffer> screen2OrigGammaRamp = new HashMap<DeviceScreenID, Buffer>(); } diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java index 7c05b8eab..045abca4c 100644 --- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java +++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java @@ -42,6 +42,7 @@ package jogamp.opengl.macosx.cgl; import java.nio.Buffer; import java.nio.FloatBuffer; +import java.nio.ShortBuffer; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -404,24 +405,29 @@ public class MacOSXCGLDrawableFactory extends GLDrawableFactoryImpl { /** Returns the length of the computed gamma ramp for this OS and hardware. Returns 0 if gamma changes are not supported. */ @Override - protected int getGammaRampLength() { + protected int getGammaRampLength(final NativeSurface surface) { return GAMMA_RAMP_LENGTH; } @Override - protected boolean setGammaRamp(final float[] ramp) { + protected boolean setGammaRamp(final NativeSurface surface, final float[] ramp) { final FloatBuffer rampNIO = Buffers.newDirectFloatBuffer(ramp); - return CGL.setGammaRamp(ramp.length, rampNIO, rampNIO, rampNIO); } @Override - protected Buffer getGammaRamp() { - return null; + protected Buffer getGammaRamp(final NativeSurface surface) { + return ShortBuffer.allocate(0); // return a dummy gamma ramp default for reset } @Override - protected void resetGammaRamp(final Buffer originalGammaRamp) { + protected void resetGammaRamp(final NativeSurface surface, final Buffer originalGammaRamp) { CGL.resetGammaRamp(); } + + @Override + protected final void resetGammaRamp(final DeviceScreenID deviceScreenID, final Buffer originalGammaRamp) { + CGL.resetGammaRamp(); + } + } diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java index 42e802a95..3daf6e1a8 100644 --- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java @@ -559,12 +559,12 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl { private static final int GAMMA_RAMP_LENGTH = 256; @Override - protected final int getGammaRampLength() { + protected final int getGammaRampLength(final NativeSurface surface) { return GAMMA_RAMP_LENGTH; } @Override - protected final boolean setGammaRamp(final float[] ramp) { + protected final boolean setGammaRamp(final NativeSurface surface, final float[] ramp) { final short[] rampData = new short[3 * GAMMA_RAMP_LENGTH]; for (int i = 0; i < GAMMA_RAMP_LENGTH; i++) { final short scaledValue = (short) (ramp[i] * 65535); @@ -573,18 +573,26 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl { rampData[i + 2 * GAMMA_RAMP_LENGTH] = scaledValue; } - final long screenDC = GDI.GetDC(0); - final boolean res = GDI.SetDeviceGammaRamp(screenDC, ShortBuffer.wrap(rampData)); - GDI.ReleaseDC(0, screenDC); + final long hDC = surface.getSurfaceHandle(); + if( 0 == hDC ) { + return false; + } + // final long screenDC = GDI.GetDC(0); + final boolean res = GDI.SetDeviceGammaRamp(hDC, ShortBuffer.wrap(rampData)); + // GDI.ReleaseDC(0, screenDC); return res; } @Override - protected final Buffer getGammaRamp() { + protected final Buffer getGammaRamp(final NativeSurface surface) { final ShortBuffer rampData = ShortBuffer.wrap(new short[3 * GAMMA_RAMP_LENGTH]); - final long screenDC = GDI.GetDC(0); - final boolean res = GDI.GetDeviceGammaRamp(screenDC, rampData); - GDI.ReleaseDC(0, screenDC); + final long hDC = surface.getSurfaceHandle(); + if( 0 == hDC ) { + return null; + } + // final long screenDC = GDI.GetDC(0); + final boolean res = GDI.GetDeviceGammaRamp(hDC, rampData); + // GDI.ReleaseDC(0, screenDC); if (!res) { return null; } @@ -592,7 +600,22 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl { } @Override - protected final void resetGammaRamp(final Buffer originalGammaRamp) { + protected final void resetGammaRamp(final NativeSurface surface, final Buffer originalGammaRamp) { + if (originalGammaRamp == null) { + // getGammaRamp failed earlier + return; + } + final long hDC = surface.getSurfaceHandle(); + if( 0 == hDC ) { + return; + } + // final long screenDC = GDI.GetDC(0); + GDI.SetDeviceGammaRamp(hDC, originalGammaRamp); + // GDI.ReleaseDC(0, hDC); + } + + @Override + protected final void resetGammaRamp(final DeviceScreenID deviceScreenID, final Buffer originalGammaRamp) { if (originalGammaRamp == null) { // getGammaRamp failed earlier return; @@ -602,6 +625,7 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl { GDI.ReleaseDC(0, screenDC); } + static interface CPUAffinity { boolean set(final int newAffinity); boolean reset(); diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java index fbab32963..60e4438d0 100644 --- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java +++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java @@ -72,6 +72,7 @@ import jogamp.opengl.GLDynamicLookupHelper; import jogamp.opengl.GLGraphicsConfigurationUtil; import jogamp.opengl.SharedResourceRunner; +import com.jogamp.common.nio.Buffers; import com.jogamp.common.util.VersionNumber; import com.jogamp.nativewindow.x11.X11GraphicsDevice; import com.jogamp.nativewindow.x11.X11GraphicsScreen; @@ -562,34 +563,34 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { private boolean gotGammaRampLength; private int gammaRampLength; @Override - protected final synchronized int getGammaRampLength() { + protected final synchronized int getGammaRampLength(final NativeSurface surface) { if (gotGammaRampLength) { return gammaRampLength; } - - final long display = getOrCreateSharedDpy(defaultDevice); + final long display = surface.getDisplayHandle(); if(0 == display) { return 0; } + final int screenIdx = surface.getScreenIndex(); final int[] size = new int[1]; - final boolean res = X11Lib.XF86VidModeGetGammaRampSize(display, - X11Lib.DefaultScreen(display), - size, 0); + final boolean res = X11Lib.XF86VidModeGetGammaRampSize(display, screenIdx, size, 0); if (!res) { return 0; } gotGammaRampLength = true; gammaRampLength = size[0]; + System.err.println("XXX: Gamma ramp size: "+gammaRampLength); return gammaRampLength; } @Override - protected final boolean setGammaRamp(final float[] ramp) { - final long display = getOrCreateSharedDpy(defaultDevice); + protected final boolean setGammaRamp(final NativeSurface surface, final float[] ramp) { + final long display = surface.getDisplayHandle(); if(0 == display) { return false; } + final int screenIdx = surface.getScreenIndex(); final int len = ramp.length; final short[] rampData = new short[len]; @@ -597,36 +598,52 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { rampData[i] = (short) (ramp[i] * 65535); } - final boolean res = X11Lib.XF86VidModeSetGammaRamp(display, - X11Lib.DefaultScreen(display), + final boolean res = X11Lib.XF86VidModeSetGammaRamp(display, screenIdx, rampData.length, rampData, 0, rampData, 0, rampData, 0); + if( DEBUG ) { + dumpRamp("SET__", rampData.length, rampData, rampData, rampData); + } return res; } + private static void dumpRamp(final String prefix, final int size, final ShortBuffer r, final ShortBuffer g, final ShortBuffer b) { + for(int i=0; i<size; i++) { + if( 0 == i % 4 ) { + System.err.printf("%n%4d/%4d %s: ", i, size, prefix); + } + System.err.printf(" [%04X %04X %04X], ", r.get(i), g.get(i), b.get(i)); + } + System.err.println(); + } + private static void dumpRamp(final String prefix, final int size, final short[] r, final short[] g, final short[] b) { + for(int i=0; i<size; i++) { + if( 0 == i % 4 ) { + System.err.printf("%n%4d/%4d %s: ", i, size, prefix); + } + System.err.printf(" [%04X %04X %04X], ", r[i], g[i], b[i]); + } + System.err.println(); + } + @Override - protected final Buffer getGammaRamp() { - final long display = getOrCreateSharedDpy(defaultDevice); + protected final Buffer getGammaRamp(final NativeSurface surface) { + final long display = surface.getDisplayHandle(); if(0 == display) { return null; } + final int screenIdx = surface.getScreenIndex(); + + final int size = getGammaRampLength(surface); - final int size = getGammaRampLength(); - final ShortBuffer rampData = ShortBuffer.wrap(new short[3 * size]); - rampData.position(0); - rampData.limit(size); - final ShortBuffer redRampData = rampData.slice(); - rampData.position(size); - rampData.limit(2 * size); - final ShortBuffer greenRampData = rampData.slice(); - rampData.position(2 * size); - rampData.limit(3 * size); - final ShortBuffer blueRampData = rampData.slice(); - - final boolean res = X11Lib.XF86VidModeGetGammaRamp(display, - X11Lib.DefaultScreen(display), + final ShortBuffer rampData = Buffers.newDirectShortBuffer(3 * size); + final ShortBuffer redRampData = Buffers.slice(rampData, 0 * size, size); + final ShortBuffer greenRampData = Buffers.slice(rampData, 1 * size, size); + final ShortBuffer blueRampData = Buffers.slice(rampData, 2 * size, size); + + final boolean res = X11Lib.XF86VidModeGetGammaRamp(display, screenIdx, size, redRampData, greenRampData, @@ -634,40 +651,62 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { if (!res) { return null; } + if( DEBUG ) { + dumpRamp("GET__", size, redRampData, greenRampData, blueRampData); + } return rampData; } @Override - protected final void resetGammaRamp(final Buffer originalGammaRamp) { + protected final void resetGammaRamp(final NativeSurface surface, final Buffer originalGammaRamp) { if (originalGammaRamp == null) { return; // getGammaRamp failed originally } - final long display = getOrCreateSharedDpy(defaultDevice); + final long display = surface.getDisplayHandle(); if(0 == display) { return; } + final int screenIdx = surface.getScreenIndex(); + + resetGammaRamp(display, screenIdx, originalGammaRamp); + } + + @Override + protected final void resetGammaRamp(final DeviceScreenID deviceScreenID, final Buffer originalGammaRamp) { + if (originalGammaRamp == null) { + return; // getGammaRamp failed originally + } + final long display = X11Util.openDisplay(deviceScreenID.deviceConnection); + if( 0 == display ) { + return; + } + try { + resetGammaRamp(display, deviceScreenID.screenIdx, originalGammaRamp); + } finally { + X11Util.closeDisplay(display); + } + } + private static final void resetGammaRamp(final long display, final int screenIdx, final Buffer originalGammaRamp) { final ShortBuffer rampData = (ShortBuffer) originalGammaRamp; final int capacity = rampData.capacity(); if ((capacity % 3) != 0) { throw new IllegalArgumentException("Must not be the original gamma ramp"); } final int size = capacity / 3; - rampData.position(0); - rampData.limit(size); - final ShortBuffer redRampData = rampData.slice(); - rampData.position(size); - rampData.limit(2 * size); - final ShortBuffer greenRampData = rampData.slice(); - rampData.position(2 * size); - rampData.limit(3 * size); - final ShortBuffer blueRampData = rampData.slice(); - - X11Lib.XF86VidModeSetGammaRamp(display, - X11Lib.DefaultScreen(display), - size, - redRampData, - greenRampData, - blueRampData); + + final ShortBuffer redRampData = Buffers.slice(rampData, 0 * size, size); + final ShortBuffer greenRampData = Buffers.slice(rampData, 1 * size, size); + final ShortBuffer blueRampData = Buffers.slice(rampData, 2 * size, size); + if( DEBUG ) { + dumpRamp("RESET", size, redRampData, greenRampData, blueRampData); + } + + X11Lib.XF86VidModeSetGammaRamp(display, screenIdx, + size, + redRampData, + greenRampData, + blueRampData); } + } 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 cd5e20c40..29c5aac70 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 @@ -52,6 +52,7 @@ import com.jogamp.opengl.test.junit.util.UITestCase; import com.jogamp.opengl.test.junit.util.QuitAdapter; import com.jogamp.opengl.util.Animator; import com.jogamp.opengl.util.AnimatorBase; +import com.jogamp.opengl.util.Gamma; import com.jogamp.opengl.util.PNGPixelRect; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; @@ -241,6 +242,9 @@ public class TestGearsES2NEWT extends UITestCase { glWindow.addKeyListener(new KeyAdapter() { int pointerIconIdx = 0; + float gamma = 1f; + float brightness = 0f; + float contrast = 1f; @Override public void keyPressed(final KeyEvent e) { @@ -264,6 +268,15 @@ public class TestGearsES2NEWT extends UITestCase { System.err.println("[set fullscreen post]: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight()+", f "+glWindow.isFullscreen()+", a "+glWindow.isAlwaysOnTop()+", "+glWindow.getInsets()); glWindow.setExclusiveContextThread(t); } }.start(); + } else if( e.getKeySymbol()== KeyEvent.VK_G ) { + new Thread() { + public void run() { + final float newGamma = gamma + ( e.isShiftDown() ? -0.1f : 0.1f ); + System.err.println("[set gamma]: "+gamma+" -> "+newGamma); + if( Gamma.setDisplayGamma(glWindow, newGamma, brightness, contrast) ) { + gamma = newGamma; + } + } }.start(); } else if(e.getKeyChar()=='a') { new Thread() { public void run() { |