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 /src/jogl/classes/jogamp/opengl | |
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.
Diffstat (limited to 'src/jogl/classes/jogamp/opengl')
4 files changed, 259 insertions, 116 deletions
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); } + } |