Failed to Set Display Mode

I’m using LWJGL .6. Any reason on why I would get the “failed to set display mode error”? It worked fine a week ago. The only change I’ve made to my computer is installed the latest nvidia drivers. I have the Gainward GForceFX5600 w/ 256 MB.

Thanks!

-Nick

I actually think I’ve found the problem. The only option my monitor has for refresh rate is 60hz. The display mode it tries to set is 72hz. Is there a way to tell it that the max refresh should be 60?

Thanks!

-Nick

I find it hard to believe that your monitor can’t do 72Hz suddenly… something’s broken. I suggest you upgrade to LWJGL 0.7 now too before you get in too deep with 0.6 :smiley:

Cas :slight_smile:

[quote]Is there a way to tell it that the max refresh should be 60?
[/quote]
Well, regardless of the cause of this new behaviour, yes there is a way of asking for 60Hz: just check that mode.freq == 60 in your DisplayMode selection code.

Actually what you should be doing is trying several modes out one after the other. It says in our not-very-clear specification that we cannot guarantee that every mode in the list of returned modes is valid which is why we can throw an Exception on setDisplayMode().

First you should filter out any unnacceptable modes. Then you should sort your display modes in order of preference and then try them all, one at a time, until one works. Only when everything has failed should you call Sys.alert() and inform the user that something is awry.

Here’s a nifty bit of code in the SPGL which does this for you:


package com.shavenpuppy.jglib;

import java.lang.reflect.Field;
import java.util.*;
import java.util.ArrayList;
import java.util.Comparator;

import org.lwjgl.DisplayMode;
import org.lwjgl.Sys;
/**
 * Display initialization.
 */
public final class Display {
      
      private static final boolean DEBUG = false;
      
      /**
       * Determine the available display modes that match the specified minimum and maximum criteria.
       * If any given criterium is specified as -1 then it is ignored.
       * 
       * @param minWidth the minimum display resolution in pixels
       * @param minHeight the minimum display resolution in pixels
       * @param maxWidth the maximum display resolution in pixels
       * @param maxHeight the maximum display resolution in pixels
       * @param minBPP the minimum bit depth per pixel
       * @param maxBPP the maximum bit depth per pixel
       * @param minFreq the minimum display frequency in Hz
       * @param maxFreq the maximum display frequency in Hz
       * @return an array of matching display modes
       */
      public static DisplayMode[] getAvailableDisplayModes(int minWidth, int minHeight, int maxWidth, int maxHeight, int minBPP, int maxBPP,
            int minFreq, int maxFreq) 
      {
            // First get the available display modes
            DisplayMode[] modes = org.lwjgl.Display.getAvailableDisplayModes();
            
            if (Sys.DEBUG || DEBUG) {
                  System.out.println("Available screen modes:");
                  for (int i = 0; i < modes.length; i ++) {
                        System.out.println(modes[i]);
                  }
            }
            
            ArrayList matches = new ArrayList(modes.length);

            for (int i = 0; i < modes.length; i ++) {
                  assert modes[i] != null : ""+i+" "+modes.length;
                  if (minWidth != -1 && modes[i].width < minWidth)
                        continue;
                  if (maxWidth != -1 && modes[i].width > maxWidth)
                        continue;
                  if (minHeight != -1 && modes[i].height < minHeight)
                        continue;
                  if (maxHeight != -1 && modes[i].height > maxHeight)
                        continue;
                  if (minBPP != -1 && modes[i].bpp < minBPP)
                        continue;
                  if (maxBPP != -1 && modes[i].bpp > maxBPP)
                        continue;
                  //if (modes[i].bpp == 24)
                  //      continue;
                  if (modes[i].freq != 0) {
                        if (minFreq != -1 && modes[i].freq < minFreq)
                              continue;
                        if (maxFreq != -1 && modes[i].freq > maxFreq)
                              continue;
                  }
                  matches.add(modes[i]);
            }
            
            DisplayMode[] ret = new DisplayMode[matches.size()];
            matches.toArray(ret);
            if (Sys.DEBUG && DEBUG) {
                  System.out.println("Filtered screen modes:");
                  for (int i = 0; i < ret.length; i ++) {
                        System.out.println(ret[i]);
                  }
            }
            
            return ret;
      }
      
      /**
       * Create the display by choosing from a list of display modes based on an order of preference.
       * You must supply a list of allowable display modes, probably by calling getAvailableDisplayModes(),
       * and an array with the order in which you would like them sorted in descending order.
       * This method attempts to create the topmost display mode; if that fails, it will try the next one,
       * and so on, until there are no modes left. If no mode is set at the end, an exception is thrown.
       * @param dm[] a list of display modes to choose from
       * @param param[] the names of the DisplayMode fields in the order in which you would like them sorted.
       * @param fullscreen whether to go fullscreen
       * @param title The app title
       * @return the chosen display mode
       * @throws NoSuchFieldException if one of the params is not a field in DisplayMode
       * @throws Exception if no display mode could be set
       * @see org.lwjgj.DisplayMode
       */
      public static DisplayMode setDisplayMode(DisplayMode[] dm, final String[] param) throws Exception {
            
            
            class Sorter implements Comparator {
                  
                  final Field[] field;
                  final int[] order;
                  final boolean[] usePreferred;
                  final int[] preferred;
                  
                  Sorter() throws NoSuchFieldException {
                        field = new Field[param.length];
                        order = new int[param.length];
                        preferred = new int[param.length];
                        usePreferred = new boolean[param.length];
                        for (int i = 0; i < field.length; i ++) {
                              int idx = param[i].indexOf('=');
                              if (idx > 0) {
                                    preferred[i] = Integer.parseInt(param[i].substring(idx + 1, param[i].length()));
                                    usePreferred[i] = true;
                                    param[i] = param[i].substring(0, idx);
                                    field[i] = DisplayMode.class.getField(param[i]);
                              } else if (param[i].charAt(0) == '-') {
                                    field[i] = DisplayMode.class.getField(param[i].substring(1));
                                    order[i] = -1;
                              } else {
                                    field[i] = DisplayMode.class.getField(param[i]);
                                    order[i] = 1;
                              }
                        }
                  }
                  
                  /**
                   * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
                   */
                  public int compare(Object o1, Object o2) {
                        DisplayMode dm1 = (DisplayMode) o1;
                        DisplayMode dm2 = (DisplayMode) o2;
                        
                        for (int i = 0; i < field.length; i ++) {
                              try {
                                    int f1 = field[i].getInt(dm1);
                                    int f2 = field[i].getInt(dm2);
                                    
                                    if (usePreferred[i] && f1 != f2) {
                                          if (f1 == preferred[i])
                                                return -1;
                                          else if (f2 == preferred[i])
                                                return 1;
                                          else {
                                                // Score according to the difference between the values
                                                int absf1 = Math.abs(f1 - preferred[i]);
                                                int absf2 = Math.abs(f2 - preferred[i]);
                                                if (absf1 < absf2)
                                                      return -1;
                                                else if (absf1 > absf2)
                                                      return 1;
                                                else
                                                      continue;
                                          }
                                    } else if (f1 < f2)
                                          return order[i];
                                    else if (f1 == f2)
                                          continue;
                                    else
                                          return -order[i];
                                    
                              } catch (Exception e) {
                                    assert false : e.getMessage();                                    
                              }
                        }
                        
                        return 0;
                  }
            }
            
            // Sort the display modes
            Arrays.sort(dm, new Sorter());
            
            // Try them out in the appropriate order
            if (Sys.DEBUG || DEBUG) {
                  System.out.println("Sorted display modes:");
                  for (int i = 0; i < dm.length; i ++) {
                        System.out.println(dm[i]);
                  }
            }
            for (int i = 0; i < dm.length; i ++) {
                  try {
                        if (Sys.DEBUG || DEBUG)
                              System.out.println("Attempting to set displaymode: "+dm[i]);
                        org.lwjgl.Display.setDisplayMode(dm[i]);
                        return dm[i];
                  } catch (Exception e) {
                        if (Sys.DEBUG || DEBUG) {
                              System.out.println("Failed to set display mode to "+dm[i]);
                              e.printStackTrace();
                        }
                  }
            }
            
            throw new Exception("Failed to set display mode.");
      }
      
}

Cas :slight_smile:

Here’s an actual example of getting the right display mode, lifted straight from Alien Flux’s init code:


            if (!AL.isCreated()) {
                  try {
                        AL.create();
                        soundPlayer = new SoundPlayer(16);
                  } catch (Exception e) {
                        e.printStackTrace();
                        Sys.alert(
                              GAME_TITLE,
                              "You need an OpenAL compatible sound card to to hear the sound effects and music in "
                                    + GAME_TITLE
                                    + ". You may have a suitable card but not have appropriate drivers. Please contact "
                                    + EMAIL_ADDRESS
                                    + " for assistance if you need help finding drivers for your sound card.");
                  }
            }

            if (!WINDOWED) {
                  try {
                        // Filter out modes smaller than 640x480, but anything bigger will do. We also pick frequencies between
                        // 60Hz and 85Hz as sometimes display drivers like to give us dodgy values which can blow up monitors.
                        // We don't care what colour depth it gives us.
                        DisplayMode[] dm = Display.getAvailableDisplayModes(640, 480, -1, -1, -1, -1, 60, 85);
                        Display.setDisplayMode(dm, new String[] {
                              "width="+options.getPreferredWidth(), // Will pick the preferred width, otherwise the nearest it can
                              "height="+options.getPreferredHeight(), // Will pick the preffered height, otherwise the nearest it can
                              "freq="+PREFERRED_FREQUENCY, // Will pick 60Hz over any other frequency, and otherwise pick the fastest it can
                              "bpp=" + (options.isTrueColour() ? "32" : "16"), // Pick 16 or 32 bit over any other depth, otherwise the nearest it can
                        });
                  
                  } catch (Exception e) {
                        e.printStackTrace();
                  }
            }
            
            try {
                  Window window;
                  if (WINDOWED) {
                        width = java.lang.Math.min(org.lwjgl.Display.getWidth(), WINDOW_WIDTH);
                        height = java.lang.Math.min(org.lwjgl.Display.getHeight(), WINDOW_HEIGHT);
                        Window.create(GAME_TITLE, 0, 0, width, height, 16, 0, 0, 0);
                  } else {
                        width = org.lwjgl.Display.getWidth();
                        height = org.lwjgl.Display.getHeight();
                        try {
                              Window.create(GAME_TITLE, 16, 0, 0, 0);
                        } catch (Exception e) {
                              width = java.lang.Math.min(org.lwjgl.Display.getWidth(), WINDOW_WIDTH);
                              height = java.lang.Math.min(org.lwjgl.Display.getHeight(), WINDOW_HEIGHT);
                              Window.create(GAME_TITLE, 0, 0, width, height, 16, 0, 0, 0);
                        }
                  }
                  GLCaps.determineAvailableExtensions();
            } catch (Exception e) {
                  e.printStackTrace();
                  cleanup();
                  Sys.alert(
                        GAME_TITLE,
                        "You need an OpenGL compatible graphics card to run "
                              + GAME_TITLE
                              + ". You may have a suitable graphics card but not have OpenGL drivers. Please contact "
                              + EMAIL_ADDRESS
                              + " for assistance if you need help finding OpenGL drivers for your graphics card.");
                  System.exit(0);
            }

            
            try {
                  Keyboard.create();
                  try { 
                        Keyboard.enableBuffer();
                        try {
                              Keyboard.enableTranslation();
                        } catch (Exception e) {
                              System.out.println("Failed to enable translation:"+e);
                        }
                  } catch (Exception e) {
                        System.out.println("Failed to enable keyboard buffer:"+e);
                  }
            } catch (Exception e) {
                  System.out.println("Failed to create keyboard:"+e);
            }
            try {
                  Mouse.create();
            } catch (Exception e) {
                  System.out.println("Failed to create mouse:"+e);
            }
            try {
                  Controller.create();
            } catch (Exception e) {
                  System.out.println("Failed to create controller:"+e);
            }
            
            // Sync to vertical blank if we can to smooth things out a bit
            if (GLCaps.WGL_EXT_swap_control && org.lwjgl.Display.getFrequency() == PREFERRED_FREQUENCY && !Sys.DEBUG) {
                  GL.wglSwapIntervalEXT(1);
            } else {
                  // Turn off swap control if we can't get 60Hz display
                  GLCaps.WGL_EXT_swap_control = false;
            }

Cas :slight_smile:

Thanks! It works.

I should hope it does!

Cas :slight_smile: