From 2b6aec3b230f99bec06ee78493dd9b748f1ec0d3 Mon Sep 17 00:00:00 2001 From: thefiddler Date: Wed, 22 Jan 2014 10:31:01 +0100 Subject: [PATCH 1/8] [OpenTK] Removed unused GraphicsMode field --- Source/OpenTK/Graphics/GraphicsMode.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/Source/OpenTK/Graphics/GraphicsMode.cs b/Source/OpenTK/Graphics/GraphicsMode.cs index 01262ad6..1068f833 100644 --- a/Source/OpenTK/Graphics/GraphicsMode.cs +++ b/Source/OpenTK/Graphics/GraphicsMode.cs @@ -22,7 +22,6 @@ namespace OpenTK.Graphics IntPtr? index = null; // The id of the pixel format or visual. static GraphicsMode defaultMode; - static IGraphicsMode implementation; static readonly object SyncRoot = new object(); #region Constructors From ff36f0f35a60e4fa38581eb6f24cac17f65cc71b Mon Sep 17 00:00:00 2001 From: thefiddler Date: Wed, 22 Jan 2014 10:35:08 +0100 Subject: [PATCH 2/8] [OpenTK] Clamp max AA level to 64x This protects against a potential denial-of-service issue during mode selection, where the platform backend will try to reduce AA level until a supported mode is found. --- Source/OpenTK/Graphics/GraphicsMode.cs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Source/OpenTK/Graphics/GraphicsMode.cs b/Source/OpenTK/Graphics/GraphicsMode.cs index 1068f833..aad7fae2 100644 --- a/Source/OpenTK/Graphics/GraphicsMode.cs +++ b/Source/OpenTK/Graphics/GraphicsMode.cs @@ -254,7 +254,14 @@ namespace OpenTK.Graphics { return samples; } - private set { samples = value; } + private set + { + // Clamp antialiasing samples to max 64x + // This protects against a potential DOS during + // mode selection, when the user requests an + // abnormally high AA level. + samples = MathHelper.Clamp(value, 0, 64); + } } #endregion From 6f3951e8251e3562f102a5c2ebc6e52683d76000 Mon Sep 17 00:00:00 2001 From: thefiddler Date: Wed, 22 Jan 2014 10:48:40 +0100 Subject: [PATCH 3/8] [OpenTK] Allow a GraphicsMode.Buffers value of 0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 0 in this case means “don’t care”. --- Source/OpenTK/Graphics/GraphicsMode.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/OpenTK/Graphics/GraphicsMode.cs b/Source/OpenTK/Graphics/GraphicsMode.cs index aad7fae2..9322ab44 100644 --- a/Source/OpenTK/Graphics/GraphicsMode.cs +++ b/Source/OpenTK/Graphics/GraphicsMode.cs @@ -43,7 +43,7 @@ namespace OpenTK.Graphics { if (depth < 0) throw new ArgumentOutOfRangeException("depth", "Must be greater than, or equal to zero."); if (stencil < 0) throw new ArgumentOutOfRangeException("stencil", "Must be greater than, or equal to zero."); - if (buffers <= 0) throw new ArgumentOutOfRangeException("buffers", "Must be greater than zero."); + if (buffers < 0) throw new ArgumentOutOfRangeException("buffers", "Must be greater than, or equal to zero."); if (samples < 0) throw new ArgumentOutOfRangeException("samples", "Must be greater than, or equal to zero."); this.Index = index; From 615df9201b136b7c54b21d1bc84b32197966979b Mon Sep 17 00:00:00 2001 From: thefiddler Date: Wed, 22 Jan 2014 10:49:27 +0100 Subject: [PATCH 4/8] [OpenTK] Moved RelaxGraphicsMode to Utilities This functionality is useful for all platform backends and is not specific to the X11 backend. --- Source/OpenTK/Platform/Utilities.cs | 108 ++++++++++++++++++ Source/OpenTK/Platform/X11/X11GraphicsMode.cs | 45 +------- 2 files changed, 110 insertions(+), 43 deletions(-) diff --git a/Source/OpenTK/Platform/Utilities.cs b/Source/OpenTK/Platform/Utilities.cs index cbf0e811..27a2d269 100644 --- a/Source/OpenTK/Platform/Utilities.cs +++ b/Source/OpenTK/Platform/Utilities.cs @@ -307,5 +307,113 @@ namespace OpenTK.Platform #endregion #endregion + + #region RelaxGraphicsMode + + internal static bool RelaxGraphicsMode(ref GraphicsMode mode) + { + ColorFormat color = mode.ColorFormat; + int depth = mode.Depth; + int stencil = mode.Stencil; + int samples = mode.Samples; + ColorFormat accum = mode.AccumulatorFormat; + int buffers = mode.Buffers; + bool stereo = mode.Stereo; + + bool success = RelaxGraphicsMode( + ref color, ref depth, ref stencil, ref samples, + ref accum, ref buffers, ref stereo); + + mode = new GraphicsMode( + color, depth, stencil, samples, + accum, buffers, stereo); + + return success; + } + + /// \internal + /// + /// Relaxes graphics mode parameters. Use this function to increase compatibility + /// on systems that do not directly support a requested GraphicsMode. For example: + /// - user requested stereoscopic rendering, but GPU does not support stereo + /// - user requseted 16x antialiasing, but GPU only supports 4x + /// + /// true, if a graphics mode parameter was relaxed, false otherwise. + /// Color bits. + /// Depth bits. + /// Stencil bits. + /// Number of antialiasing samples. + /// Accumulator buffer bits. + /// Number of rendering buffers (1 for single buffering, 2+ for double buffering, 0 for don't care). + /// Stereoscopic rendering enabled/disabled. + internal static bool RelaxGraphicsMode(ref ColorFormat color, ref int depth, ref int stencil, ref int samples, ref ColorFormat accum, ref int buffers, ref bool stereo) + { + // Parameters are relaxed in order of importance. + // - Accumulator buffers are way outdated as a concept, + // so they go first. + // - Triple+ buffering is generally not supported by the + // core WGL/GLX/AGL/CGL/EGL specs, so we clamp + // to double-buffering as a second step. (If this doesn't help + // we will also fall back to undefined single/double buffering + // as a last resort). + // - AA samples are an easy way to increase compatibility + // so they go next. + // - Stereoscopic is only supported on very few GPUs + // (Quadro/FirePro series) so it goes next. + // - The rest of the parameters then follow. + + if (accum != 0) + { + accum = 0; + return true; + } + + if (buffers > 2) + { + buffers = 2; + return true; + } + + if (samples > 0) + { + samples = Math.Max(samples - 2, 0); + return true; + } + + if (stereo) + { + stereo = false; + return true; + } + + if (stencil != 0) + { + stencil = 0; + return true; + } + + if (depth != 0) + { + depth = 0; + return true; + } + + if (color != 24) + { + color = 24; + return true; + } + + if (buffers != 0) + { + buffers = 0; + return true; + } + + // no parameters left to relax, fail + return false; + } + + #endregion } } diff --git a/Source/OpenTK/Platform/X11/X11GraphicsMode.cs b/Source/OpenTK/Platform/X11/X11GraphicsMode.cs index 1c019036..000f45ee 100644 --- a/Source/OpenTK/Platform/X11/X11GraphicsMode.cs +++ b/Source/OpenTK/Platform/X11/X11GraphicsMode.cs @@ -52,49 +52,8 @@ namespace OpenTK.Platform.X11 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."); + if (!Utilities.RelaxGraphicsMode(ref color, ref depth, ref stencil, ref samples, ref accum, ref buffers, ref stereo)) + throw new GraphicsModeException("Requested GraphicsMode not available."); } } while (visual == IntPtr.Zero); From 6ba475e23fd0c7ed0a7409b8a0ee55f9c97ea99f Mon Sep 17 00:00:00 2001 From: thefiddler Date: Wed, 22 Jan 2014 10:49:55 +0100 Subject: [PATCH 5/8] [Win] Use RelaxGraphicsMode to find optimal mode --- .../Platform/Windows/WinGraphicsMode.cs | 207 +++++++++--------- 1 file changed, 108 insertions(+), 99 deletions(-) diff --git a/Source/OpenTK/Platform/Windows/WinGraphicsMode.cs b/Source/OpenTK/Platform/Windows/WinGraphicsMode.cs index 1a97fa72..8550ddf8 100644 --- a/Source/OpenTK/Platform/Windows/WinGraphicsMode.cs +++ b/Source/OpenTK/Platform/Windows/WinGraphicsMode.cs @@ -96,114 +96,123 @@ namespace OpenTK.Platform.Windows // hardware acceleration (e.g. we are running in a VM or in a remote desktop // connection), this method will return 0 formats and we will fall back to // ChoosePixelFormatPFD. - GraphicsMode ChoosePixelFormatARB(IntPtr device, GraphicsMode mode) + GraphicsMode ChoosePixelFormatARB(IntPtr device, GraphicsMode desired_mode) { GraphicsMode created_mode = null; + GraphicsMode mode = new GraphicsMode(desired_mode); if (Wgl.SupportsExtension("WGL_ARB_pixel_format") && Wgl.SupportsFunction("wglChoosePixelFormatARB")) { - List attributes = new List(); - attributes.Add((int)WGL_ARB_pixel_format.AccelerationArb); - attributes.Add((int)WGL_ARB_pixel_format.FullAccelerationArb); - - attributes.Add((int)WGL_ARB_pixel_format.DrawToWindowArb); - attributes.Add(1); - - if (mode.ColorFormat.Red > 0) - { - attributes.Add((int)WGL_ARB_pixel_format.RedBitsArb); - attributes.Add(mode.ColorFormat.Red); - } - - if (mode.ColorFormat.Green > 0) - { - attributes.Add((int)WGL_ARB_pixel_format.GreenBitsArb); - attributes.Add(mode.ColorFormat.Green); - } - - if (mode.ColorFormat.Blue > 0) - { - attributes.Add((int)WGL_ARB_pixel_format.BlueBitsArb); - attributes.Add(mode.ColorFormat.Blue); - } - - if (mode.ColorFormat.Alpha > 0) - { - attributes.Add((int)WGL_ARB_pixel_format.AlphaBitsArb); - attributes.Add(mode.ColorFormat.Alpha); - } - - if (mode.Depth > 0) - { - attributes.Add((int)WGL_ARB_pixel_format.DepthBitsArb); - attributes.Add(mode.Depth); - } - - if (mode.Stencil > 0) - { - attributes.Add((int)WGL_ARB_pixel_format.StencilBitsArb); - attributes.Add(mode.Stencil); - } - - if (mode.AccumulatorFormat.Red > 0) - { - attributes.Add((int)WGL_ARB_pixel_format.AccumRedBitsArb); - attributes.Add(mode.AccumulatorFormat.Red); - } - - if (mode.AccumulatorFormat.Green > 0) - { - attributes.Add((int)WGL_ARB_pixel_format.AccumGreenBitsArb); - attributes.Add(mode.AccumulatorFormat.Green); - } - - if (mode.AccumulatorFormat.Blue > 0) - { - attributes.Add((int)WGL_ARB_pixel_format.AccumBlueBitsArb); - attributes.Add(mode.AccumulatorFormat.Blue); - } - - if (mode.AccumulatorFormat.Alpha > 0) - { - attributes.Add((int)WGL_ARB_pixel_format.AccumAlphaBitsArb); - attributes.Add(mode.AccumulatorFormat.Alpha); - } - - if (mode.Samples > 0 && - Wgl.SupportsExtension("WGL_ARB_multisample")) - { - attributes.Add((int)WGL_ARB_multisample.SampleBuffersArb); - attributes.Add(1); - attributes.Add((int)WGL_ARB_multisample.SamplesArb); - attributes.Add(mode.Samples); - } - - if (mode.Buffers > 0) - { - attributes.Add((int)WGL_ARB_pixel_format.DoubleBufferArb); - attributes.Add(mode.Buffers > 1 ? 1 : 0); - } - - if (mode.Stereo) - { - attributes.Add((int)WGL_ARB_pixel_format.StereoArb); - attributes.Add(1); - } - - attributes.Add(0); - attributes.Add(0); - int[] format = new int[1]; int count; - if (Wgl.Arb.ChoosePixelFormat(device, attributes.ToArray(), null, format.Length, format, out count) - && count > 0) + List attributes = new List(); + bool retry = false; + + do { - created_mode = DescribePixelFormatARB(device, format[0]); - } - else - { - Debug.Print("[WGL] ChoosePixelFormatARB failed with {0}", Marshal.GetLastWin32Error()); + attributes.Clear(); + attributes.Add((int)WGL_ARB_pixel_format.AccelerationArb); + attributes.Add((int)WGL_ARB_pixel_format.FullAccelerationArb); + attributes.Add((int)WGL_ARB_pixel_format.DrawToWindowArb); + attributes.Add(1); + + if (mode.ColorFormat.Red > 0) + { + attributes.Add((int)WGL_ARB_pixel_format.RedBitsArb); + attributes.Add(mode.ColorFormat.Red); + } + + if (mode.ColorFormat.Green > 0) + { + attributes.Add((int)WGL_ARB_pixel_format.GreenBitsArb); + attributes.Add(mode.ColorFormat.Green); + } + + if (mode.ColorFormat.Blue > 0) + { + attributes.Add((int)WGL_ARB_pixel_format.BlueBitsArb); + attributes.Add(mode.ColorFormat.Blue); + } + + if (mode.ColorFormat.Alpha > 0) + { + attributes.Add((int)WGL_ARB_pixel_format.AlphaBitsArb); + attributes.Add(mode.ColorFormat.Alpha); + } + + if (mode.Depth > 0) + { + attributes.Add((int)WGL_ARB_pixel_format.DepthBitsArb); + attributes.Add(mode.Depth); + } + + if (mode.Stencil > 0) + { + attributes.Add((int)WGL_ARB_pixel_format.StencilBitsArb); + attributes.Add(mode.Stencil); + } + + if (mode.AccumulatorFormat.Red > 0) + { + attributes.Add((int)WGL_ARB_pixel_format.AccumRedBitsArb); + attributes.Add(mode.AccumulatorFormat.Red); + } + + if (mode.AccumulatorFormat.Green > 0) + { + attributes.Add((int)WGL_ARB_pixel_format.AccumGreenBitsArb); + attributes.Add(mode.AccumulatorFormat.Green); + } + + if (mode.AccumulatorFormat.Blue > 0) + { + attributes.Add((int)WGL_ARB_pixel_format.AccumBlueBitsArb); + attributes.Add(mode.AccumulatorFormat.Blue); + } + + if (mode.AccumulatorFormat.Alpha > 0) + { + attributes.Add((int)WGL_ARB_pixel_format.AccumAlphaBitsArb); + attributes.Add(mode.AccumulatorFormat.Alpha); + } + + if (mode.Samples > 0 && + Wgl.SupportsExtension("WGL_ARB_multisample")) + { + attributes.Add((int)WGL_ARB_multisample.SampleBuffersArb); + attributes.Add(1); + attributes.Add((int)WGL_ARB_multisample.SamplesArb); + attributes.Add(mode.Samples); + } + + if (mode.Buffers > 0) + { + attributes.Add((int)WGL_ARB_pixel_format.DoubleBufferArb); + attributes.Add(mode.Buffers > 1 ? 1 : 0); + } + + if (mode.Stereo) + { + attributes.Add((int)WGL_ARB_pixel_format.StereoArb); + attributes.Add(1); + } + + attributes.Add(0); + attributes.Add(0); + + if (Wgl.Arb.ChoosePixelFormat(device, attributes.ToArray(), null, format.Length, format, out count) + && count > 0) + { + created_mode = DescribePixelFormatARB(device, format[0]); + retry = false; + } + else + { + Debug.Print("[WGL] ChoosePixelFormatARB failed with {0}", Marshal.GetLastWin32Error()); + retry = Utilities.RelaxGraphicsMode(ref mode); + } } + while (retry); } else { From 0575e63a275aba44aa83882e6fbe8b813ff25ee9 Mon Sep 17 00:00:00 2001 From: thefiddler Date: Wed, 22 Jan 2014 11:03:40 +0100 Subject: [PATCH 6/8] [Max] Use RelaxGraphicsMode to find optimal mode --- Source/OpenTK/Platform/MacOS/AglContext.cs | 56 ++++++------------- .../Platform/MacOS/MacOSGraphicsMode.cs | 43 ++++++++++++-- 2 files changed, 55 insertions(+), 44 deletions(-) diff --git a/Source/OpenTK/Platform/MacOS/AglContext.cs b/Source/OpenTK/Platform/MacOS/AglContext.cs index d1de6664..f8e0fe0c 100644 --- a/Source/OpenTK/Platform/MacOS/AglContext.cs +++ b/Source/OpenTK/Platform/MacOS/AglContext.cs @@ -52,8 +52,6 @@ namespace OpenTK.Platform.MacOS DisplayDevice device; bool mIsFullscreen = false; - readonly MacOSGraphicsMode ModeSelector = new MacOSGraphicsMode(); - public AglContext(GraphicsMode mode, IWindowInfo window, IGraphicsContext shareContext) { Debug.Print("Context Type: {0}", shareContext); @@ -103,6 +101,7 @@ namespace OpenTK.Platform.MacOS aglAttributes.Add((int)pixelFormatAttribute); aglAttributes.Add(value); } + void CreateContext(GraphicsMode mode, CarbonWindowInfo carbonWindow, IntPtr shareContextRef, bool fullscreen) { Debug.Print("AGL pixel format attributes:"); @@ -110,51 +109,30 @@ namespace OpenTK.Platform.MacOS AGLPixelFormat myAGLPixelFormat; // Choose a pixel format with the attributes we specified. - if (fullscreen) - { - IntPtr gdevice; - IntPtr cgdevice = GetQuartzDevice(carbonWindow); + IntPtr gdevice; + IntPtr cgdevice = GetQuartzDevice(carbonWindow); - if (cgdevice == IntPtr.Zero) - cgdevice = (IntPtr)DisplayDevice.Default.Id; + if (cgdevice == IntPtr.Zero) + cgdevice = (IntPtr)DisplayDevice.Default.Id; - OSStatus status = Carbon.API.DMGetGDeviceByDisplayID(cgdevice, out gdevice, false); + OSStatus status = Carbon.API.DMGetGDeviceByDisplayID(cgdevice, out gdevice, false); - if (status != OSStatus.NoError) - throw new MacOSException(status, "DMGetGDeviceByDisplayID failed."); - - myAGLPixelFormat = ModeSelector.SelectPixelFormat( - mode.ColorFormat, mode.Depth, mode.Stencil, mode.Samples, - mode.AccumulatorFormat, mode.Buffers, mode.Stereo, - true, gdevice); - - Agl.AglError err = Agl.GetError(); - if (myAGLPixelFormat == IntPtr.Zero || err == Agl.AglError.BadPixelFormat) - { - Debug.Print("Failed to create full screen pixel format."); - Debug.Print("Trying again to create a non-fullscreen pixel format."); - - CreateContext(mode, carbonWindow, shareContextRef, false); - return; - } - } - else - { - myAGLPixelFormat = ModeSelector.SelectPixelFormat( - mode.ColorFormat, mode.Depth, mode.Stencil, mode.Samples, - mode.AccumulatorFormat, mode.Buffers, mode.Stereo, - false, IntPtr.Zero); - MyAGLReportError("aglChoosePixelFormat"); - } - + if (status != OSStatus.NoError) + throw new MacOSException(status, "DMGetGDeviceByDisplayID failed."); + + IGraphicsMode selector = new MacOSGraphicsMode(gdevice); + Mode = selector.SelectGraphicsMode( + mode.ColorFormat, mode.Depth, mode.Stencil, mode.Samples, + mode.AccumulatorFormat, mode.Buffers, mode.Stereo); + MyAGLReportError("aglChoosePixelFormat"); + Debug.Print("Creating AGL context. Sharing with {0}", shareContextRef); - + myAGLPixelFormat = Mode.Index.Value; + // create the context and share it with the share reference. Handle = new ContextHandle(Agl.aglCreateContext(myAGLPixelFormat, shareContextRef)); MyAGLReportError("aglCreateContext"); - Mode = ModeSelector.GetGraphicsModeFromPixelFormat(myAGLPixelFormat); - // Free the pixel format from memory. Agl.aglDestroyPixelFormat(myAGLPixelFormat); MyAGLReportError("aglDestroyPixelFormat"); diff --git a/Source/OpenTK/Platform/MacOS/MacOSGraphicsMode.cs b/Source/OpenTK/Platform/MacOS/MacOSGraphicsMode.cs index 604973e2..7f09155b 100644 --- a/Source/OpenTK/Platform/MacOS/MacOSGraphicsMode.cs +++ b/Source/OpenTK/Platform/MacOS/MacOSGraphicsMode.cs @@ -37,14 +37,47 @@ namespace OpenTK.Platform.MacOS class MacOSGraphicsMode : IGraphicsMode { + readonly IntPtr Device; + + public MacOSGraphicsMode(IntPtr device) + { + Device = device; + } + #region IGraphicsMode Members public GraphicsMode SelectGraphicsMode(ColorFormat color, int depth, int stencil, int samples, ColorFormat accum, int buffers, bool stereo) { - IntPtr pixelformat = SelectPixelFormat( - color, depth, stencil, samples, accum, buffers, stereo, - false, IntPtr.Zero); + IntPtr pixelformat; + do + { + pixelformat = SelectPixelFormat( + color, depth, stencil, samples, accum, buffers, stereo, + true, Device); + + Agl.AglError err = Agl.GetError(); + if (pixelformat == IntPtr.Zero || err == Agl.AglError.BadPixelFormat) + { + Debug.Print("Failed to create full screen pixel format."); + Debug.Print("Trying again to create a non-fullscreen pixel format."); + pixelformat = SelectPixelFormat( + color, depth, stencil, samples, accum, buffers, stereo, + false, IntPtr.Zero); + } + + if (pixelformat == IntPtr.Zero) + { + if (!Utilities.RelaxGraphicsMode( + ref color, ref depth, ref stencil, ref samples, ref accum, + ref buffers, ref stereo)) + { + throw new GraphicsModeException("Requested GraphicsMode not available."); + } + } + } + while (pixelformat == IntPtr.Zero); + return GetGraphicsModeFromPixelFormat(pixelformat); } @@ -52,7 +85,7 @@ namespace OpenTK.Platform.MacOS #region Internal Members - internal GraphicsMode GetGraphicsModeFromPixelFormat(IntPtr pixelformat) + GraphicsMode GetGraphicsModeFromPixelFormat(IntPtr pixelformat) { int r, g, b, a; Agl.aglDescribePixelFormat(pixelformat, Agl.PixelFormatAttribute.AGL_RED_SIZE, out r); @@ -75,7 +108,7 @@ namespace OpenTK.Platform.MacOS depth, stencil, samples, new ColorFormat(ar, ag, ab, aa), buffers + 1, stereo != 0); } - internal IntPtr SelectPixelFormat(ColorFormat color, int depth, int stencil, int samples, + IntPtr SelectPixelFormat(ColorFormat color, int depth, int stencil, int samples, ColorFormat accum, int buffers, bool stereo, bool fullscreen, IntPtr device) { List attribs = new List(); From 417a6bedc16278dacb446d4b134a228afa947abd Mon Sep 17 00:00:00 2001 From: thefiddler Date: Wed, 22 Jan 2014 11:37:37 +0100 Subject: [PATCH 7/8] [SDL2] Use RelaxGraphicsMode to find optimal mode For SDL2, RelaxGraphicsMode requires us to clear context attributes between consecutive attempts. This is implemented by calling ClearGLAttributes(). --- .../Platform/SDL2/Sdl2GraphicsContext.cs | 41 ++++++++++++++++++- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/Source/OpenTK/Platform/SDL2/Sdl2GraphicsContext.cs b/Source/OpenTK/Platform/SDL2/Sdl2GraphicsContext.cs index c7714b58..75818496 100644 --- a/Source/OpenTK/Platform/SDL2/Sdl2GraphicsContext.cs +++ b/Source/OpenTK/Platform/SDL2/Sdl2GraphicsContext.cs @@ -63,8 +63,20 @@ namespace OpenTK.Platform.SDL2 { lock (SDL.Sync) { - SetGLAttributes(mode, shareContext, major, minor, flags); - SdlContext = new ContextHandle(SDL.GL.CreateContext(Window.Handle)); + bool retry = false; + do + { + SetGLAttributes(mode, shareContext, major, minor, flags); + SdlContext = new ContextHandle(SDL.GL.CreateContext(Window.Handle)); + + // If we failed to create a valid context, relax the GraphicsMode + // and try again. + retry = + SdlContext == ContextHandle.Zero && + Utilities.RelaxGraphicsMode(ref mode); + } + while (retry); + if (SdlContext == ContextHandle.Zero) { var error = SDL.GetError(); @@ -152,12 +164,37 @@ namespace OpenTK.Platform.SDL2 stereo != 0 ? true : false); } + static void ClearGLAttributes() + { + SDL.GL.SetAttribute(ContextAttribute.ACCUM_ALPHA_SIZE, 0); + SDL.GL.SetAttribute(ContextAttribute.ACCUM_RED_SIZE, 0); + SDL.GL.SetAttribute(ContextAttribute.ACCUM_GREEN_SIZE, 0); + SDL.GL.SetAttribute(ContextAttribute.ACCUM_BLUE_SIZE, 0); + SDL.GL.SetAttribute(ContextAttribute.DOUBLEBUFFER, 0); + SDL.GL.SetAttribute(ContextAttribute.ALPHA_SIZE, 0); + SDL.GL.SetAttribute(ContextAttribute.RED_SIZE, 0); + SDL.GL.SetAttribute(ContextAttribute.GREEN_SIZE, 0); + SDL.GL.SetAttribute(ContextAttribute.BLUE_SIZE, 0); + SDL.GL.SetAttribute(ContextAttribute.DEPTH_SIZE, 0); + SDL.GL.SetAttribute(ContextAttribute.MULTISAMPLEBUFFERS, 0); + SDL.GL.SetAttribute(ContextAttribute.MULTISAMPLESAMPLES, 0); + SDL.GL.SetAttribute(ContextAttribute.STENCIL_SIZE, 0); + SDL.GL.SetAttribute(ContextAttribute.STEREO, 0); + SDL.GL.SetAttribute(ContextAttribute.CONTEXT_MAJOR_VERSION, 1); + SDL.GL.SetAttribute(ContextAttribute.CONTEXT_MINOR_VERSION, 0); + SDL.GL.SetAttribute(ContextAttribute.CONTEXT_FLAGS, 0); + SDL.GL.SetAttribute(ContextAttribute.CONTEXT_EGL, 0); + SDL.GL.SetAttribute(ContextAttribute.CONTEXT_PROFILE_MASK, 0); + SDL.GL.SetAttribute(ContextAttribute.SHARE_WITH_CURRENT_CONTEXT, 0); + } + static void SetGLAttributes(GraphicsMode mode, IGraphicsContext shareContext, int major, int minor, GraphicsContextFlags flags) { ContextProfileFlags cpflags = 0; + ClearGLAttributes(); if (mode.AccumulatorFormat.BitsPerPixel > 0) { From 06a3d7e1a7de5afe506b99c300a70a5da7aad452 Mon Sep 17 00:00:00 2001 From: "Stefanos A." Date: Wed, 22 Jan 2014 23:25:11 +0100 Subject: [PATCH 8/8] [OpenTK] Don't skip AA modes in RelaxGraphicsMode Previously, specifying an odd AA mode (e.g. 5x) would have been relaxed to 0x. Now, it will be correctly relaxed to 4x. --- Source/OpenTK/Platform/Utilities.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/OpenTK/Platform/Utilities.cs b/Source/OpenTK/Platform/Utilities.cs index 27a2d269..82fa91ab 100644 --- a/Source/OpenTK/Platform/Utilities.cs +++ b/Source/OpenTK/Platform/Utilities.cs @@ -376,7 +376,7 @@ namespace OpenTK.Platform if (samples > 0) { - samples = Math.Max(samples - 2, 0); + samples = Math.Max(samples - 1, 0); return true; }