1 /* 2 * Copyright (c) 2002-2008 LWJGL Project 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: 8 * 9 * * Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * * Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * * Neither the name of 'LWJGL' nor the names of 17 * its contributors may be used to endorse or promote products derived 18 * from this software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 27 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 28 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 package org.lwjgl.util; 33 34 import java.util.ArrayList; 35 import java.util.Arrays; 36 import java.util.Comparator; 37 38 import org.lwjgl.LWJGLException; 39 import org.lwjgl.LWJGLUtil; 40 import org.lwjgl.opengl.DisplayMode; 41 42 /** 43 * Display initialization utility, that can be used to find display modes and pick 44 * one for you based on your criteria. 45 * @author $Author$ 46 * @version $Revision$ 47 * $Id$ 48 */ 49 public final class Display { 50 51 private static final boolean DEBUG = false; 52 53 /** 54 * Determine the available display modes that match the specified minimum and maximum criteria. 55 * If any given criterium is specified as -1 then it is ignored. 56 * 57 * @param minWidth the minimum display resolution in pixels 58 * @param minHeight the minimum display resolution in pixels 59 * @param maxWidth the maximum display resolution in pixels 60 * @param maxHeight the maximum display resolution in pixels 61 * @param minBPP the minimum bit depth per pixel 62 * @param maxBPP the maximum bit depth per pixel 63 * @param minFreq the minimum display frequency in Hz 64 * @param maxFreq the maximum display frequency in Hz 65 * @return an array of matching display modes 66 */ getAvailableDisplayModes(int minWidth, int minHeight, int maxWidth, int maxHeight, int minBPP, int maxBPP, int minFreq, int maxFreq)67 public static DisplayMode[] getAvailableDisplayModes(int minWidth, int minHeight, int maxWidth, int maxHeight, int minBPP, int maxBPP, 68 int minFreq, int maxFreq) throws LWJGLException 69 { 70 // First get the available display modes 71 DisplayMode[] modes = org.lwjgl.opengl.Display.getAvailableDisplayModes(); 72 73 if (LWJGLUtil.DEBUG || DEBUG) { 74 System.out.println("Available screen modes:"); 75 for ( DisplayMode mode : modes ) { 76 System.out.println(mode); 77 } 78 } 79 80 ArrayList<DisplayMode> matches = new ArrayList<DisplayMode>(modes.length); 81 82 for (int i = 0; i < modes.length; i ++) { 83 assert modes[i] != null : ""+i+" "+modes.length; 84 if (minWidth != -1 && modes[i].getWidth() < minWidth) 85 continue; 86 if (maxWidth != -1 && modes[i].getWidth() > maxWidth) 87 continue; 88 if (minHeight != -1 && modes[i].getHeight() < minHeight) 89 continue; 90 if (maxHeight != -1 && modes[i].getHeight() > maxHeight) 91 continue; 92 if (minBPP != -1 && modes[i].getBitsPerPixel() < minBPP) 93 continue; 94 if (maxBPP != -1 && modes[i].getBitsPerPixel() > maxBPP) 95 continue; 96 //if (modes[i].bpp == 24) 97 // continue; 98 if (modes[i].getFrequency() != 0) { 99 if (minFreq != -1 && modes[i].getFrequency() < minFreq) 100 continue; 101 if (maxFreq != -1 && modes[i].getFrequency() > maxFreq) 102 continue; 103 } 104 matches.add(modes[i]); 105 } 106 107 DisplayMode[] ret = new DisplayMode[matches.size()]; 108 matches.toArray(ret); 109 if (LWJGLUtil.DEBUG && DEBUG) { 110 System.out.println("Filtered screen modes:"); 111 for ( DisplayMode mode : ret ) { 112 System.out.println(mode); 113 } 114 } 115 116 return ret; 117 } 118 119 /** 120 * Create the display by choosing from a list of display modes based on an order of preference. 121 * You must supply a list of allowable display modes, probably by calling getAvailableDisplayModes(), 122 * and an array with the order in which you would like them sorted in descending order. 123 * This method attempts to create the topmost display mode; if that fails, it will try the next one, 124 * and so on, until there are no modes left. If no mode is set at the end, an exception is thrown. 125 * @param dm a list of display modes to choose from 126 * @param param the names of the DisplayMode fields in the order in which you would like them sorted. 127 * @return the chosen display mode 128 * @throws NoSuchFieldException if one of the params is not a field in DisplayMode 129 * @throws Exception if no display mode could be set 130 * @see org.lwjgl.opengl.DisplayMode 131 */ setDisplayMode(DisplayMode[] dm, final String[] param)132 public static DisplayMode setDisplayMode(DisplayMode[] dm, final String[] param) throws Exception { 133 134 class FieldAccessor { 135 final String fieldName; 136 final int order; 137 final int preferred; 138 final boolean usePreferred; 139 FieldAccessor(String fieldName, int order, int preferred, boolean usePreferred) { 140 this.fieldName = fieldName; 141 this.order = order; 142 this.preferred = preferred; 143 this.usePreferred = usePreferred; 144 } 145 int getInt(DisplayMode mode) { 146 if ("width".equals(fieldName)) { 147 return mode.getWidth(); 148 } 149 if ("height".equals(fieldName)) { 150 return mode.getHeight(); 151 } 152 if ("freq".equals(fieldName)) { 153 return mode.getFrequency(); 154 } 155 if ("bpp".equals(fieldName)) { 156 return mode.getBitsPerPixel(); 157 } 158 throw new IllegalArgumentException("Unknown field "+fieldName); 159 } 160 } 161 162 class Sorter implements Comparator<DisplayMode> { 163 164 final FieldAccessor[] accessors; 165 166 Sorter() { 167 accessors = new FieldAccessor[param.length]; 168 for (int i = 0; i < accessors.length; i ++) { 169 int idx = param[i].indexOf('='); 170 if (idx > 0) { 171 accessors[i] = new FieldAccessor(param[i].substring(0, idx), 0, Integer.parseInt(param[i].substring(idx + 1, param[i].length())), true); 172 } else if (param[i].charAt(0) == '-') { 173 accessors[i] = new FieldAccessor(param[i].substring(1), -1, 0, false); 174 } else { 175 accessors[i] = new FieldAccessor(param[i], 1, 0, false); 176 } 177 } 178 } 179 180 /** 181 * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object) 182 */ 183 public int compare(DisplayMode dm1, DisplayMode dm2) { 184 for ( FieldAccessor accessor : accessors ) { 185 int f1 = accessor.getInt(dm1); 186 int f2 = accessor.getInt(dm2); 187 188 if ( accessor.usePreferred && f1 != f2 ) { 189 if ( f1 == accessor.preferred ) 190 return -1; 191 else if ( f2 == accessor.preferred ) 192 return 1; 193 else { 194 // Score according to the difference between the values 195 int absf1 = Math.abs(f1 - accessor.preferred); 196 int absf2 = Math.abs(f2 - accessor.preferred); 197 if ( absf1 < absf2 ) 198 return -1; 199 else if ( absf1 > absf2 ) 200 return 1; 201 else 202 continue; 203 } 204 } else if ( f1 < f2 ) 205 return accessor.order; 206 else if ( f1 == f2 ) 207 continue; 208 else 209 return -accessor.order; 210 } 211 212 return 0; 213 } 214 } 215 216 // Sort the display modes 217 Arrays.sort(dm, new Sorter()); 218 219 // Try them out in the appropriate order 220 if (LWJGLUtil.DEBUG || DEBUG) { 221 System.out.println("Sorted display modes:"); 222 for ( DisplayMode aDm : dm ) { 223 System.out.println(aDm); 224 } 225 } 226 for ( DisplayMode aDm : dm ) { 227 try { 228 if ( LWJGLUtil.DEBUG || DEBUG ) 229 System.out.println("Attempting to set displaymode: " + aDm); 230 org.lwjgl.opengl.Display.setDisplayMode(aDm); 231 return aDm; 232 } catch (Exception e) { 233 if ( LWJGLUtil.DEBUG || DEBUG ) { 234 System.out.println("Failed to set display mode to " + aDm); 235 e.printStackTrace(); 236 } 237 } 238 } 239 240 throw new Exception("Failed to set display mode."); 241 } 242 243 } 244