Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

[Mac] Improved stability for NSOpenGLPixelFormat

Non-accelerated contexts are now considered iff no accelerated contexts
are available. Additionally, a GraphicsException will be thrown if
context construction fails for any reason, instead of causing a runtime
crash.
  • Loading branch information...
commit 32958ffccef33030f5eaf614dc6df81306da0fc2 1 parent d81fc0e
@thefiddler thefiddler authored
Showing with 75 additions and 22 deletions.
  1. +75 −22 Source/OpenTK/Platform/MacOS/CocoaContext.cs
View
97 Source/OpenTK/Platform/MacOS/CocoaContext.cs
@@ -112,6 +112,42 @@ private void AddPixelAttrib(List<NSOpenGLPixelFormatAttribute> attributes, NSOpe
private void CreateContext(GraphicsMode mode, CocoaWindowInfo cocoaWindow, IntPtr shareContextRef, int majorVersion, int minorVersion, bool fullscreen)
{
// Prepare attributes
+ IntPtr pixelFormat = SelectPixelFormat(mode, majorVersion, minorVersion);
+ if (pixelFormat == IntPtr.Zero)
+ {
+ throw new GraphicsException(String.Format(
+ "Failed to contruct NSOpenGLPixelFormat for GraphicsMode '{0}'",
+ mode));
+ }
+
+ // Create context
+ var context = Cocoa.SendIntPtr(NSOpenGLContext, Selector.Alloc);
+ context = Cocoa.SendIntPtr(context, Selector.Get("initWithFormat:shareContext:"), pixelFormat, shareContextRef);
+ if (context == IntPtr.Zero)
+ {
+ throw new GraphicsException(String.Format(
+ "Failed to construct NSOpenGLContext",
+ mode));
+ }
+
+ // Release pixel format
+ Cocoa.SendVoid(pixelFormat, Selector.Release);
+ pixelFormat = IntPtr.Zero;
+
+ // Attach the view
+ Cocoa.SendVoid(context, Selector.Get("setView:"), cocoaWindow.ViewHandle);
+ Cocoa.SendVoid(cocoaWindow.ViewHandle, Selector.Get("setWantsBestResolutionOpenGLSurface:"), true);
+
+ // Finalize
+ Handle = new ContextHandle(context);
+ Mode = GetGraphicsMode(context);
+
+ Update(cocoaWindow);
+ MakeCurrent(cocoaWindow);
+ }
+
+ private IntPtr SelectPixelFormat(GraphicsMode mode, int majorVersion, int minorVersion)
+ {
List<NSOpenGLPixelFormatAttribute> attributes = new List<NSOpenGLPixelFormatAttribute>();
var profile = NSOpenGLProfile.VersionLegacy;
@@ -129,31 +165,50 @@ private void CreateContext(GraphicsMode mode, CocoaWindowInfo cocoaWindow, IntPt
Debug.Indent();
AddPixelAttrib(attributes, NSOpenGLPixelFormatAttribute.OpenGLProfile, (int)profile);
- AddPixelAttrib(attributes, NSOpenGLPixelFormatAttribute.DoubleBuffer);
- AddPixelAttrib(attributes, NSOpenGLPixelFormatAttribute.Accelerated);
- AddPixelAttrib(attributes, NSOpenGLPixelFormatAttribute.ColorSize, mode.ColorFormat.BitsPerPixel);
+
+ if (mode.ColorFormat.BitsPerPixel > 0)
+ {
+ AddPixelAttrib(attributes, NSOpenGLPixelFormatAttribute.ColorSize, mode.ColorFormat.BitsPerPixel);
+ }
if (mode.Depth > 0)
+ {
AddPixelAttrib(attributes, NSOpenGLPixelFormatAttribute.DepthSize, mode.Depth);
-
+ }
+
if (mode.Stencil > 0)
+ {
AddPixelAttrib(attributes, NSOpenGLPixelFormatAttribute.StencilSize, mode.Stencil);
+ }
if (mode.AccumulatorFormat.BitsPerPixel > 0)
{
AddPixelAttrib(attributes, NSOpenGLPixelFormatAttribute.AccumSize, mode.AccumulatorFormat.BitsPerPixel);
}
-
+
if (mode.Samples > 1)
{
AddPixelAttrib(attributes, NSOpenGLPixelFormatAttribute.SampleBuffers, 1);
AddPixelAttrib(attributes, NSOpenGLPixelFormatAttribute.Samples, mode.Samples);
}
+ if (mode.Buffers > 1)
+ {
+ AddPixelAttrib(attributes, NSOpenGLPixelFormatAttribute.DoubleBuffer);
+ }
+
+ // If at least a single accelerated pixel format is available,
+ // then use that. If no accelerated formats are available, fall
+ // back to software rendering.
+ if (IsAccelerationSupported())
+ {
+ AddPixelAttrib(attributes, NSOpenGLPixelFormatAttribute.Accelerated);
+ }
+
AddPixelAttrib(attributes, (NSOpenGLPixelFormatAttribute)0);
-
+
Debug.Unindent();
-
+
Debug.Write("Attribute array: ");
for (int i = 0; i < attributes.Count; i++)
Debug.Write(attributes[i].ToString() + " ");
@@ -170,24 +225,22 @@ private void CreateContext(GraphicsMode mode, CocoaWindowInfo cocoaWindow, IntPt
}
}
- // Create context
- var context = Cocoa.SendIntPtr(NSOpenGLContext, Selector.Alloc);
- context = Cocoa.SendIntPtr(context, Selector.Get("initWithFormat:shareContext:"), pixelFormat, shareContextRef);
-
- // Release pixel format
- Cocoa.SendVoid(pixelFormat, Selector.Release);
- pixelFormat = IntPtr.Zero;
+ return pixelFormat;
+ }
- // Attach the view
- Cocoa.SendVoid(context, Selector.Get("setView:"), cocoaWindow.ViewHandle);
- Cocoa.SendVoid(cocoaWindow.ViewHandle, Selector.Get("setWantsBestResolutionOpenGLSurface:"), true);
+ bool IsAccelerationSupported()
+ {
+ IntPtr pf = IntPtr.Zero;
+ int count = 0;
+ Cgl.ChoosePixelFormat(new int[] { (int)Cgl.PixelFormatBool.Accelerated, 0 },
+ ref pf, ref count);
- // Finalize
- Handle = new ContextHandle(context);
- Mode = GetGraphicsMode(context);
+ if (pf != IntPtr.Zero)
+ {
+ Cgl.DestroyPixelFormat(pf);
+ }
- Update(cocoaWindow);
- MakeCurrent(cocoaWindow);
+ return pf != IntPtr.Zero;
}
private GraphicsMode GetGraphicsMode(IntPtr context)
Please sign in to comment.
Something went wrong with that request. Please try again.