运行使用OpenGL的MonoMac示例时出现System.Exception

时间:2012-08-27 15:34:05

标签: macos mono monodevelop

这是我对stackOverflow的第一篇文章,所以我希望你对我很好:)。在使用XCode v4.4,MonoDevelop v3.0.5以及MonoMac(v2.10.9)git hub的最新开发分支设置我的系统后,在运行包含OpenGL的MonoMac示例时,我不断获得这些异常,其他任何示例都按预期工作。以下是异常的堆栈跟踪: -

2012-08-27 15:23:17.117 NeHeLesson1[229:1207] invalid pixel format
2012-08-27 15:23:17.119 NeHeLesson1[229:1207] invalid context

Unhandled Exception: System.Exception: Invalid parameters to context creation
at MonoMac.OpenGL.CGLContext..ctor (intptr) <0x0006f>
at MonoMac.AppKit.NSOpenGLContext.get_CGLContext () <0x00053>
at NeHeLesson1.MyOpenGLView.SetupDisplayLink () <0x00089>
at NeHeLesson1.MyOpenGLView..ctor (System.Drawing.RectangleF,MonoMac.AppKit.NSOpenGLContext) <0x00283>
at NeHeLesson1.MyOpenGLView..ctor (System.Drawing.RectangleF) <0x00033>
at (wrapper dynamic-method) object.ee521f2b-bbc7-4e1d-ad69-1022ce59ef12 (intptr,MonoMac.ObjCRuntime.Selector,System.Drawing.RectangleF) <0x00077>
at (wrapper native-to-managed) object.ee521f2b-bbc7-4e1d-ad69-1022ce59ef12 (intptr,MonoMac.ObjCRuntime.Selector,System.Drawing.RectangleF) <0x0008f>
at (wrapper managed-to-native) MonoMac.ObjCRuntime.Messaging.IntPtr_objc_msgSendSuper (intptr,intptr) <0x00003>
at MonoMac.AppKit.NSWindowController.get_Window () <0x0007b>
at NeHeLesson1.MainWindowController.get_Window () <0x00013>
at NeHeLesson1.AppDelegate.FinishedLaunching (MonoMac.Foundation.NSObject) <0x0003b>
at (wrapper dynamic-method) object.[NeHeLesson1.AppDelegate.Void FinishedLaunching(MonoMac.Foundation.NSObject)] (MonoMac.Foundation.NSObject,MonoMac.ObjCRuntime.Selector,MonoMac.Foundation.NSObject) <0x00033>
at (wrapper native-to-managed) object.[NeHeLesson1.AppDelegate.Void FinishedLaunching(MonoMac.Foundation.NSObject)] (MonoMac.Foundation.NSObject,MonoMac.ObjCRuntime.Selector,MonoMac.Foundation.NSObject) <0x000fb>
at (wrapper managed-to-native) MonoMac.AppKit.NSApplication.NSApplicationMain (int,string[]) <0x00003>
at MonoMac.AppKit.NSApplication.Main (string[]) <0x00017>
at NeHeLesson1.MainClass.Main (string[]) <0x00017>

[ERROR] FATAL UNHANDLED EXCEPTION: System.Exception: Invalid parameters to context creation
at MonoMac.OpenGL.CGLContext..ctor (intptr) <0x0006f>
at MonoMac.AppKit.NSOpenGLContext.get_CGLContext () <0x00053>
at NeHeLesson1.MyOpenGLView.SetupDisplayLink () <0x00089>
at NeHeLesson1.MyOpenGLView..ctor (System.Drawing.RectangleF,MonoMac.AppKit.NSOpenGLContext) <0x00283>
at NeHeLesson1.MyOpenGLView..ctor (System.Drawing.RectangleF) <0x00033>
at (wrapper dynamic-method) object.ee521f2b-bbc7-4e1d-ad69-1022ce59ef12 (intptr,MonoMac.ObjCRuntime.Selector,System.Drawing.RectangleF) <0x00077>
at (wrapper native-to-managed) object.ee521f2b-bbc7-4e1d-ad69-1022ce59ef12 (intptr,MonoMac.ObjCRuntime.Selector,System.Drawing.RectangleF) <0x0008f>
at (wrapper managed-to-native) MonoMac.ObjCRuntime.Messaging.IntPtr_objc_msgSendSuper (intptr,intptr) <0x00003>
at MonoMac.AppKit.NSWindowController.get_Window () <0x0007b>
at NeHeLesson1.MainWindowController.get_Window () <0x00013>
at NeHeLesson1.AppDelegate.FinishedLaunching (MonoMac.Foundation.NSObject) <0x0003b>
at (wrapper dynamic-method) object.[NeHeLesson1.AppDelegate.Void FinishedLaunching(MonoMac.Foundation.NSObject)] (MonoMac.Foundation.NSObject,MonoMac.ObjCRuntime.Selector,MonoMac.Foundation.NSObject) <0x00033>
at (wrapper native-to-managed) object.[NeHeLesson1.AppDelegate.Void FinishedLaunching(MonoMac.Foundation.NSObject)] (MonoMac.Foundation.NSObject,MonoMac.ObjCRuntime.Selector,MonoMac.Foundation.NSObject) <0x000fb>
at (wrapper managed-to-native) MonoMac.AppKit.NSApplication.NSApplicationMain (int,string[]) <0x00003>
at MonoMac.AppKit.NSApplication.Main (string[]) <0x00017>
at NeHeLesson1.MainClass.Main (string[]) <0x00017>

导致错误的代码是: -

using System;
using System.Collections.Generic;
using System.Linq;
using System.Drawing;
using MonoMac.Foundation;
using MonoMac.AppKit;
using MonoMac.CoreVideo;
using MonoMac.CoreGraphics;
using MonoMac.OpenGL;

namespace NeHeLesson1
{
    public partial class MyOpenGLView : MonoMac.AppKit.NSView
    {

        NSOpenGLContext openGLContext;
        NSOpenGLPixelFormat pixelFormat;

        MainWindowController controller;

        CVDisplayLink displayLink;

        NSObject notificationProxy;

        [Export("initWithFrame:")]
        public MyOpenGLView (RectangleF frame) : this(frame, null)
        {
        }

        public MyOpenGLView (RectangleF frame, NSOpenGLContext context) : base(frame)
        {
            var attribs = new object [] {
                NSOpenGLPixelFormatAttribute.Accelerated,
                NSOpenGLPixelFormatAttribute.NoRecovery,
                NSOpenGLPixelFormatAttribute.DoubleBuffer,
                NSOpenGLPixelFormatAttribute.ColorSize, 24,
                NSOpenGLPixelFormatAttribute.DepthSize, 16 };

            pixelFormat = new NSOpenGLPixelFormat (attribs);

            if (pixelFormat == null)
                Console.WriteLine ("No OpenGL pixel format");

            // NSOpenGLView does not handle context sharing, so we draw to a custom NSView instead
            openGLContext = new NSOpenGLContext (pixelFormat, context);

            openGLContext.MakeCurrentContext ();

            // Synchronize buffer swaps with vertical refresh rate
            openGLContext.SwapInterval = true;

            // Initialize our newly created view.
            InitGL ();

            SetupDisplayLink();

            // Look for changes in view size
            // Note, -reshape will not be called automatically on size changes because NSView does not export it to override 
            notificationProxy = NSNotificationCenter.DefaultCenter.AddObserver (NSView.NSViewGlobalFrameDidChangeNotification, HandleReshape);
        }

        public override void DrawRect (RectangleF dirtyRect)
        {
            // Ignore if the display link is still running
            if (!displayLink.IsRunning && controller != null)
                DrawView ();
        }

        public override bool AcceptsFirstResponder ()
        {
            // We want this view to be able to receive key events
            return true;
        }

        public override void LockFocus ()
        {
            base.LockFocus ();
            if (openGLContext.View != this)
                openGLContext.View = this;
        }

        public override void KeyDown (NSEvent theEvent)
        {
            controller.KeyDown (theEvent);
        }

        public override void MouseDown (NSEvent theEvent)
        {
            controller.MouseDown (theEvent);
        }

        // All Setup For OpenGL Goes Here
        public bool InitGL ()
        {
                // Enables Smooth Shading  
                GL.ShadeModel (ShadingModel.Smooth);
                // Set background color to black     
                GL.ClearColor (Color.Black);

                // Setup Depth Testing

                // Depth Buffer setup
                GL.ClearDepth (1.0);
                // Enables Depth testing
                GL.Enable (EnableCap.DepthTest);
                // The type of depth testing to do
                GL.DepthFunc (DepthFunction.Lequal);

                // Really Nice Perspective Calculations
                GL.Hint (HintTarget.PerspectiveCorrectionHint, HintMode.Nicest);

                return true;
        }

        private void DrawView ()
        {
            // This method will be called on both the main thread (through -drawRect:) and a secondary thread (through the display link rendering loop)
            // Also, when resizing the view, -reshape is called on the main thread, but we may be drawing on a secondary thread
            // Add a mutex around to avoid the threads accessing the context simultaneously 
            openGLContext.CGLContext.Lock ();

            // Make sure we draw to the right context
            openGLContext.MakeCurrentContext ();

            // Delegate to the scene object for rendering
            controller.Scene.DrawGLScene ();

            openGLContext.FlushBuffer ();

            openGLContext.CGLContext.Unlock ();
        }


        private void SetupDisplayLink ()
        {
            // Create a display link capable of being used with all active displays
            displayLink = new CVDisplayLink ();

            // Set the renderer output callback function
            displayLink.SetOutputCallback (MyDisplayLinkOutputCallback);

            // Set the display link for the current renderer
            CGLContext cglContext = openGLContext.CGLContext;
            CGLPixelFormat cglPixelFormat = PixelFormat.CGLPixelFormat;
            displayLink.SetCurrentDisplay (cglContext, cglPixelFormat);

        }

        public CVReturn MyDisplayLinkOutputCallback (CVDisplayLink displayLink, ref CVTimeStamp inNow, ref CVTimeStamp inOutputTime, CVOptionFlags flagsIn, ref CVOptionFlags flagsOut)
        {
            CVReturn result = GetFrameForTime (inOutputTime);

            return result;
        }


        private CVReturn GetFrameForTime (CVTimeStamp outputTime)
        {
            // There is no autorelease pool when this method is called because it will be called from a background thread
            // It's important to create one or you will leak objects
            using (NSAutoreleasePool pool = new NSAutoreleasePool ()) {

                // Update the animation
                DrawView ();
            }

            return CVReturn.Success;

        }

        public NSOpenGLContext OpenGLContext {
            get { return openGLContext; }
        }

        public NSOpenGLPixelFormat PixelFormat {
            get { return pixelFormat; }
        }

        public MainWindowController MainController {
            set { controller = value; }
        }

        public void UpdateView ()
        {
            // This method will be called on the main thread when resizing, but we may be drawing on a secondary thread through the display link
            // Add a mutex around to avoid the threads accessing the context simultaneously
            openGLContext.CGLContext.Lock ();

            // Delegate to the scene object to update for a change in the view size
            controller.Scene.ResizeGLScene (Bounds);
            openGLContext.Update ();

            openGLContext.CGLContext.Unlock ();
        }

        private void HandleReshape (NSNotification note)
        {
            UpdateView ();
        }

        public void StartAnimation ()
        {
            if (displayLink != null && !displayLink.IsRunning)
                displayLink.Start ();
        }

        public void StopAnimation ()
        {
            if (displayLink != null && displayLink.IsRunning)
                displayLink.Stop ();
        }

        // Clean up the notifications
        public void DeAllocate()
        {
            displayLink.Stop();
            displayLink.SetOutputCallback(null);

            NSNotificationCenter.DefaultCenter.RemoveObserver(notificationProxy); 
        }

        [Export("toggleFullScreen:")]
        public void toggleFullScreen (NSObject sender)
        {
                controller.toggleFullScreen (sender);
        }       
    }
}

scene.cs

namespace NeHeLesson1
{
    public class Scene : NSObject
    {
        public Scene () : base()
        {
        }

        // Resize And Initialize The GL Window 
        //      - See also the method in the MyOpenGLView Constructor about the NSView.NSViewGlobalFrameDidChangeNotification
        public void ResizeGLScene (RectangleF bounds)
        {
            // Reset The Current Viewport
            GL.Viewport (0, 0, (int)bounds.Size.Width, (int)bounds.Size.Height);
            // Select The Projection Matrix
            GL.MatrixMode (MatrixMode.Projection);
            // Reset The Projection Matrix
            GL.LoadIdentity ();

            // Set perspective here - Calculate The Aspect Ratio Of The Window
            Perspective (45, bounds.Size.Width / bounds.Size.Height, 0.1, 100);

            // Select The Modelview Matrix
            GL.MatrixMode (MatrixMode.Modelview);
            // Reset The Modelview Matrix
            GL.LoadIdentity ();
        }

        // This creates a symmetric frustum.
        // It converts to 6 params (l, r, b, t, n, f) for glFrustum()
        // from given 4 params (fovy, aspect, near, far)
        public static void Perspective (double fovY, double aspectRatio, double front, double back)
        {
            const double DEG2RAD = Math.PI / 180;

            // tangent of half fovY
            double tangent = Math.Tan (fovY / 2 * DEG2RAD);

            // half height of near plane
            double height = front * tangent;

            // half width of near plane
            double width = height * aspectRatio;

            // params: left, right, bottom, top, near, far
            GL.Frustum (-width, width, -height, height, front, back);
        }

        // This method renders our scene and where all of your drawing code will go.
        // The main thing to note is that we've factored the drawing code out of the NSView subclass so that
        // the full-screen and non-fullscreen views share the same states for rendering 
        public bool DrawGLScene ()
        {
            // Clear The Screen And The Depth Buffer
            GL.Clear (ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
            // Reset The Current Modelview Matrix
            GL.LoadIdentity ();

            return true;
        }

    }
}

希望有人可以帮助我解决这个问题,因为它停止运行MonoMac和MonoGameFrameWork,我错过了我的设置。顺便说一句,我能够运行所有OpenGLExtentions Viewer测试,所以我的openGL似乎可以工作。

Jase

1 个答案:

答案 0 :(得分:-1)

我会做的事情......

  1. 转到http://www.go-mono.com/mono-downloads/download.html
  2. 下载Mono 2.10.9 SDK
  3. 确保您已安装X11 - http://www.simplehelp.net/2006/10/22/how-to-install-x11-in-os-x/
  4. 如果您想使用MonoGame然后执行“git clone git@github.com:mono / MonoGame.git”,然后执行“cd MonoGame”,则执行命令“git submodule update --init --recursive”,这样下载Samples和StarterKit子模块。
  5. 注意:如上所述,NeheLesson1不是MonoGame框架示例。它是纯OpenGL样本。 MonoGame Framework示例可以在上面克隆的MonoGame仓库的Samples和StarterKit子目录中找到。

    我希望这会有所帮助。