[X11] Improve GraphicsMode fallback (fixes issue #23)
authorthefiddler <stapostol@gmail.com>
Fri, 27 Dec 2013 12:01:21 +0000 (14:01 +0200)
committerthefiddler <stapostol@gmail.com>
Fri, 27 Dec 2013 12:01:21 +0000 (14:01 +0200)
When the user requests a GraphicsMode that is not directly supported
by the GPU/drivers, we should relax the requested parameters until
we find a supported mode. An exception should only be thrown when
there is no usable mode.

This makes the X11 backend match the behavior of Windows. The SDL/X11
backend works a little bit differently, in that it falls back to the
a default mode directly if the requested mode is not available. There
is nothing we can do about that.

Source/OpenTK/Platform/X11/X11GraphicsMode.cs

index 789281b..1c01903 100644 (file)
@@ -39,19 +39,68 @@ namespace OpenTK.Platform.X11
             // The actual GraphicsMode that will be selected.
             IntPtr visual = IntPtr.Zero;
             IntPtr display = API.DefaultDisplay;
-            
-            // Try to select a visual using Glx.ChooseFBConfig and Glx.GetVisualFromFBConfig.
-            // This is only supported on GLX 1.3 - if it fails, fall back to Glx.ChooseVisual.
-            visual = SelectVisualUsingFBConfig(color, depth, stencil, samples, accum, buffers, stereo);
-            
-            if (visual == IntPtr.Zero)
-                visual = SelectVisualUsingChooseVisual(color, depth, stencil, samples, accum, buffers, stereo);
-            
-            if (visual == IntPtr.Zero)
-                throw new GraphicsModeException("Requested GraphicsMode not available.");
-            
+
+            do
+            {
+                // Try to select a visual using Glx.ChooseFBConfig and Glx.GetVisualFromFBConfig.
+                // This is only supported on GLX 1.3 - if it fails, fall back to Glx.ChooseVisual.
+                visual = SelectVisualUsingFBConfig(color, depth, stencil, samples, accum, buffers, stereo);
+                
+                if (visual == IntPtr.Zero)
+                    visual = SelectVisualUsingChooseVisual(color, depth, stencil, samples, accum, buffers, stereo);
+                
+                if (visual == IntPtr.Zero)
+                {
+                    // Relax parameters and retry
+                    if (stereo)
+                    {
+                        stereo = false;
+                        continue;
+                    }
+
+                    if (accum != 0)
+                    {
+                        accum = 0;
+                        continue;
+                    }
+                    
+                    if (samples > 0)
+                    {
+                        samples = Math.Max(samples - 2, 0);
+                        continue;
+                    }
+                    
+                    if (stencil != 0)
+                    {
+                        stencil = 0;
+                        continue;
+                    }
+                    
+                    if (depth != 0)
+                    {
+                        depth = 0;
+                        continue;
+                    }
+                    
+                    if (color != 24)
+                    {
+                        color = 24;
+                        continue;
+                    }
+
+                    if (buffers != 0)
+                    {
+                        buffers = 0;
+                        continue;
+                    }
+
+                    throw new GraphicsModeException("Requested GraphicsMode not available.");
+                }
+            }
+            while (visual == IntPtr.Zero);
+
             XVisualInfo info = (XVisualInfo)Marshal.PtrToStructure(visual, typeof(XVisualInfo));
-            
+
             // See what we *really* got:
             int r, g, b, a;
             Glx.GetConfig(display, ref info, GLXAttribute.ALPHA_SIZE, out a);