All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.jogamp.newt.MonitorMode Maven / Gradle / Ivy

/**
 * Copyright 2013 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 com.jogamp.newt;

import java.util.Comparator;

import javax.media.nativewindow.util.DimensionImmutable;
import javax.media.nativewindow.util.RectangleImmutable;
import javax.media.nativewindow.util.SurfaceSize;

import com.jogamp.newt.util.MonitorModeUtil;


/**
 * Immutable MonitorMode Class, consisting of it's read only components:
*
    *
  • nativeId
  • *
  • {@link SizeAndRRate}, consist out of non rotated {@link #getSurfaceSize() surface size}, {@link #getRefreshRate() refresh rate} and {@link #getFlags() flags}.
  • *
  • rotation, measured counter clockwise (CCW)
  • *
* * Aquire and filter MonitorMode
*
    *
  • {@link MonitorDevice} Selection: *
      *
    • A List of all {@link MonitorDevice}s is accessible via {@link Screen#getMonitorDevices()}.
    • *
    • The main monitor used by a windows is accessible via {@link Window#getMainMonitor()}.
    • *
    • The main monitor covering an arbitrary rectnagle is accessible via {@link Screen#getMainMonitor(RectangleImmutable)}.
    • *
  • *
  • The current MonitorMode can be obtained via {@link MonitorDevice#getCurrentMode()}.
  • *
  • The original MonitorMode can be obtained via {@link MonitorDevice#getOriginalMode()}.
  • *
  • {@link MonitorMode} Filtering: *
      *
    • A {@link MonitorDevice}'s MonitorModes is accessible via {@link MonitorDevice#getSupportedModes()}.
    • *
    • You may utilize {@link MonitorModeUtil} to filter and select a desired MonitorMode.
    • *
  • *
*
* * Changing MonitorMode
*
    *
  • Use {@link MonitorDevice#setCurrentMode(MonitorMode)} * to change the current MonitorMode for all {@link Screen}s referenced via the {@link Screen#getFQName() full qualified name (FQN)}.
  • *
  • The {@link MonitorDevice#getOriginalMode() original mode} is restored when *
      *
    • the last FQN referenced Screen closes.
    • *
    • the JVM shuts down.
    • *
  • *
*
* Example for changing the MonitorMode: *
        // Pick the monitor:
        // Either the one used by a window ..
        MonitorDevice monitor = window.getMainMonitor();

        // Or arbitrary from the list ..
        List allMonitor = getMonitorDevices();
        MonitorDevice monitor = allMonitor.get(0);

        // Current and original modes ..
        MonitorMode mmCurrent = monitor.queryCurrentMode();
        MonitorMode mmOrig = monitor.getOriginalMode();

        // Target resolution
        Dimension res = new Dimension(800, 600);

        // Target refresh rate shall be similar to current one ..
        float freq = mmCurrent.getRefreshRate();

        // Target rotation shall be similar to current one
        int rot = mmCurrent.getRotation();

        // Filter criterias sequential out of all available MonitorMode of the chosen MonitorDevice
        List monitorModes = monitor.getSupportedModes();
        monitorModes = MonitorModeUtil.filterByFlags(monitorModes, 0); // no interlace, double-scan etc
        monitorModes = MonitorModeUtil.filterByRotation(monitorModes, rot);
        monitorModes = MonitorModeUtil.filterByResolution(monitorModes, res);
        monitorModes = MonitorModeUtil.filterByRate(monitorModes, freq);
        monitorModes = MonitorModeUtil.getHighestAvailableBpp(monitorModes);

        // pick 1st one and set to current ..
        MonitorMode mm = monitorModes.get(0);
        monitor.setCurrentMode(mm);
 * 
*/ public class MonitorMode implements Comparable { /** Comparator for 2 {@link MonitorMode}s, following comparison order as described in {@link MonitorMode#compareTo(MonitorMode)}, returning the ascending order. */ public static final Comparator monitorModeComparator = new Comparator() { @Override public int compare(MonitorMode mm1, MonitorMode mm2) { return mm1.compareTo(mm2); } }; /** Comparator for 2 {@link MonitorMode}s, following comparison order as described in {@link MonitorMode#compareTo(MonitorMode)}, returning the descending order. */ public static final Comparator monitorModeComparatorInv = new Comparator() { @Override public int compare(MonitorMode mm1, MonitorMode mm2) { return mm2.compareTo(mm1); } }; /** * Immutable surfaceSize, flags and refreshRate Class, consisting of it's read only components:
*
    *
  • nativeId
  • *
  • {@link SurfaceSize} surface memory size
  • *
  • flags
  • *
  • refresh rate
  • *
*/ public static class SizeAndRRate implements Comparable { /** Non rotated surface size */ public final SurfaceSize surfaceSize; /** Mode bitfield flags, i.e. {@link #FLAG_DOUBLESCAN}, {@link #FLAG_INTERLACE}, .. */ public final int flags; /** Vertical refresh rate */ public final float refreshRate; public final int hashCode; public SizeAndRRate(SurfaceSize surfaceSize, float refreshRate, int flags) { if(null==surfaceSize) { throw new IllegalArgumentException("surfaceSize must be set ("+surfaceSize+")"); } this.surfaceSize=surfaceSize; this.flags = flags; this.refreshRate=refreshRate; this.hashCode = getHashCode(); } private final static String STR_INTERLACE = "Interlace"; private final static String STR_DOUBLESCAN = "DoubleScan"; private final static String STR_SEP = ", "; public static final StringBuilder flags2String(int flags) { final StringBuilder sb = new StringBuilder(); boolean sp = false; if( 0 != ( flags & FLAG_INTERLACE ) ) { sb.append(STR_INTERLACE); sp = true; } if( 0 != ( flags & FLAG_DOUBLESCAN ) ) { if( sp ) { sb.append(STR_SEP); } sb.append(STR_DOUBLESCAN); sp = true; } return sb; } @Override public final String toString() { return surfaceSize+" @ "+refreshRate+" Hz, flags ["+flags2String(flags).toString()+"]"; } /** *

* Compares {@link SurfaceSize#compareTo(SurfaceSize) surfaceSize} 1st, then {@link #flags}, then {@link #refreshRate}. *

*

* Flags are compared as follows: *

         *   NONE > DOUBLESCAN > INTERLACE
         * 
*

*

* Refresh rate differences of < 0.01 are considered equal (epsilon). *

* {@inheritDoc} */ @Override public int compareTo(final SizeAndRRate sszr) { final int rssz = surfaceSize.compareTo(sszr.surfaceSize); if( 0 != rssz ) { return rssz; } final int tflags = 0 == flags ? Integer.MAX_VALUE : flags; // normalize NONE final int xflags = 0 == sszr.flags ? Integer.MAX_VALUE : sszr.flags; // normalize NONE if( tflags == xflags ) { final float refreshEpsilon = 0.01f; // reasonable sorting granularity of refresh rate final float drate = refreshRate - sszr.refreshRate; if( Math.abs(drate) < refreshEpsilon ) { return 0; } else if( drate > refreshEpsilon ) { return 1; } else { return -1; } } else { if(tflags > xflags) { return 1; } else if(tflags < xflags) { return -1; } return 0; } } /** * Tests equality of two {@link SizeAndRRate} objects * by evaluating equality of it's components:
*
    *
  • surfaceSize
  • *
  • refreshRate
  • *
  • flags
  • *
*/ @Override public final boolean equals(Object obj) { if (this == obj) { return true; } if (obj instanceof SizeAndRRate) { final SizeAndRRate p = (SizeAndRRate)obj; return surfaceSize.equals(p.surfaceSize) && flags == p.flags && refreshRate == p.refreshRate ; } return false; } /** * Returns a combined hash code of it's elements:
*
    *
  • surfaceSize
  • *
  • flags
  • *
  • refreshRate
  • *
*/ @Override public final int hashCode() { return hashCode; } private final int getHashCode() { // 31 * x == (x << 5) - x int hash = 31 + surfaceSize.hashCode(); hash = ((hash << 5) - hash) + flags; hash = ((hash << 5) - hash) + (int)(refreshRate*100.0f); return hash; } } /** zero rotation, compared to normal settings */ public static final int ROTATE_0 = 0; /** 90 degrees CCW rotation */ public static final int ROTATE_90 = 90; /** 180 degrees CCW rotation */ public static final int ROTATE_180 = 180; /** 270 degrees CCW rotation */ public static final int ROTATE_270 = 270; /** Frame is split into two fields. See {@link #getFlags()}. */ public static final int FLAG_INTERLACE = 1 << 0; /** Lines are doubled. See {@link #getFlags()}. */ public static final int FLAG_DOUBLESCAN = 1 << 1; /** The immutable native Id of this instance, which may not be unique. */ private final int nativeId; private final SizeAndRRate sizeAndRRate; private final int rotation; private final int hashCode; public static boolean isRotationValid(int rotation) { return rotation == MonitorMode.ROTATE_0 || rotation == MonitorMode.ROTATE_90 || rotation == MonitorMode.ROTATE_180 || rotation == MonitorMode.ROTATE_270 ; } /** * @param sizeAndRRate the surface size and refresh rate mode * @param rotation the screen rotation, measured counter clockwise (CCW) */ public MonitorMode(int nativeId, SizeAndRRate sizeAndRRate, int rotation) { if ( !isRotationValid(rotation) ) { throw new RuntimeException("invalid rotation: "+rotation); } this.nativeId = nativeId; this.sizeAndRRate = sizeAndRRate; this.rotation = rotation; this.hashCode = getHashCode(); } /** * Creates a user instance w/o {@link #getId() identity} to filter our matching modes w/ identity. *

* See {@link com.jogamp.newt.util.MonitorModeUtil} for filter utilities. *

* @param surfaceSize * @param refreshRate * @param flags * @param rotation */ public MonitorMode(SurfaceSize surfaceSize, float refreshRate, int flags, int rotation) { this(0, new SizeAndRRate(surfaceSize, refreshRate, flags), rotation); } /** @return the immutable native Id of this mode, may not be unique, may be 0. */ public final int getId() { return nativeId; } /** Returns the surfaceSize and refreshRate instance. */ public final SizeAndRRate getSizeAndRRate() { return sizeAndRRate; } /** Returns the unrotated {@link SurfaceSize} */ public final SurfaceSize getSurfaceSize() { return sizeAndRRate.surfaceSize; } /** Returns the vertical refresh rate. */ public final float getRefreshRate() { return sizeAndRRate.refreshRate; } /** Returns bitfield w/ flags, i.e. {@link #FLAG_DOUBLESCAN}, {@link #FLAG_INTERLACE}, .. */ public final int getFlags() { return sizeAndRRate.flags; } /** Returns the CCW rotation of this mode */ public final int getRotation() { return rotation; } /** Returns the rotated screen width, * derived from getMonitorMode().getSurfaceSize().getResolution() * and getRotation() */ public final int getRotatedWidth() { return getRotatedWH(true); } /** Returns the rotated screen height, * derived from getMonitorMode().getSurfaceSize().getResolution() * and getRotation() */ public final int getRotatedHeight() { return getRotatedWH(false); } @Override public final String toString() { return "[Id "+Display.toHexString(nativeId)+", " + sizeAndRRate + ", " + rotation + " degr]"; } /** *

* Compares {@link SizeAndRRate#compareTo(SizeAndRRate) sizeAndRRate} 1st, then {@link #rotation}. *

*

* Rotation is compared inverted, i.e. 360 - rotation, * so the lowest rotation reflects a higher value. *

*

* Order of comparing MonitorMode: *

    *
  • resolution
  • *
  • bits per pixel
  • *
  • flags
  • *
  • refresh rate
  • *
  • rotation
  • *
*

* {@inheritDoc} */ @Override public int compareTo(final MonitorMode mm) { final int c = sizeAndRRate.compareTo(mm.sizeAndRRate); if( 0 != c ) { return c; } final int trot = 360 - rotation; // normalize rotation final int xrot = 360 - mm.rotation; // normalize rotation if(trot > xrot) { return 1; } else if(trot < xrot) { return -1; } return 0; } /** * Tests equality of two {@link MonitorMode} objects * by evaluating equality of it's components:
*
    *
  • nativeId
  • *
  • sizeAndRRate
  • *
  • rotation
  • *
*/ @Override public final boolean equals(Object obj) { if (this == obj) { return true; } if (obj instanceof MonitorMode) { MonitorMode sm = (MonitorMode)obj; return sm.nativeId == this.nativeId && sm.sizeAndRRate.equals(sizeAndRRate) && sm.rotation == this.rotation ; } return false; } /** * Returns a combined hash code of it's elements:
*
    *
  • nativeId
  • *
  • sizeAndRRate
  • *
  • rotation
  • *
*/ @Override public final int hashCode() { return hashCode; } private final int getHashCode() { // 31 * x == (x << 5) - x int hash = 31 + getId(); hash = ((hash << 5) - hash) + sizeAndRRate.hashCode(); hash = ((hash << 5) - hash) + getRotation(); return hash; } private final int getRotatedWH(boolean width) { final DimensionImmutable d = sizeAndRRate.surfaceSize.getResolution(); final boolean swap = MonitorMode.ROTATE_90 == rotation || MonitorMode.ROTATE_270 == rotation ; if ( ( width && swap ) || ( !width && !swap ) ) { return d.getHeight(); } return d.getWidth(); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy