
OpenTK Mac OS X support.
Posted Tuesday, 18 March, 2008 - 16:39 by kanato inWell, I thought I would let you know I've been working on writing support for Mac OS X for OpenTK. I've successfully wrapped window creation and event processing through the Carbon API. I need to work on keyboard and mouse event processions, then AGL wrapping, then I think I'll be to the point where I can integrate with OpenTK. Hopefully I can get there by early next week.


Comments
Re: OpenTK Mac OS X support.
Awesome news! Let me know if you need help with anything.
Re: OpenTK Mac OS X support.
What's the rule on converting GL* types to c# types? I'm guessing GLint -> int is ok, but is GLboolean -> bool ok? Or do I need to use an int type?
Edit: nevermind, I see it's defined as unsigned char in the headers.
Do you have any tips on Marshalling? I think I understand that I need to pin arrays to a fixed pointer to marshal them, but I don't know if there are any other gotchas.
Re: OpenTK Mac OS X support.
As a rule of thumb, just write a
DllImportwith the correct signature and let the runtime handle the details for you (pinning etc), unless it is performance-critical code.For example:
This should cover just about 90% of all p/invoke cases.
Void pointers can be turned into
IntPtrs, and char arrays should be made intostrings (in parameters) orStringBuilders (out parameters). Generally, the biggest issue is converting structs with unions or embedded arrays/strings - just make a post if anything strange shows up ;)Another complication has to do with 64bit datatypes: do
ints change bitness from 32- to 64bit compilers (i.e. 32bit on 32bit compilers and 64bit on 64bit compilers)? If so, int parameters should be defined asIntPtrs, which is a bit ugly (but necessary).Re: OpenTK Mac OS X support.
Ok, here is a patch which adds preliminary MacOS X support: http://agate.sourceforge.net/download/macos.patch
This patch should be considered preliminary, and not for production use. Keyboard support is incomplete, and there are some exceptions when windows are closed, and I haven't gotten GLControl to work right yet. So I don't recommend commiting this to SVN right now.
I put everything in a MacOS folder and namespace, instead of the OSX folder / namespace. The reasoning for this is that since CarbonLib predates OSX, it should be possible, with a bit of work, to add support for Mac OS 9. I don't have a Mac which can run OS 9 however, and there is no official support from Mono for Mac OS prior to 10.3 or so. So that may not ever be a reality. Plus I think MacOS is easier to read than OSX. But if you don't like it, I can change everything to using OSX instead.
I've wrapped Agl context creation, Carbon window creation, mouse and keyboard events. Several of the examples work (Simple Window, Immediate mode, Display Lists, Fonts, Text, Texture Mapping). There are some artifacts with the text, just above and below the glyphs. I think this might be related to artifacts mentioned in other threads on the forum.
Apparently my MacMini only supports OpenGL 1.2, so VBO and GLSL don't work. The GLU Tesselate example doesn't work, and I'm not sure why. Other GLU functions like Glu.LookAt work, and extension loading for GLU seems to work.
Things that need to be resolved with GameWindow:
A couple of other thoughts:
Have you thought of abstracting all the platform stuff to some sort of class factory? Rather than have lines like "if (Configuration.RunningOnOSX)" all over the place, just have a static class in Platform, which a hidden implementation object that each platform implements, and it just creates whatever objects are necessary. If you are interested, I can code this up, it won't take long.
I noticed when the GameWindow is closed, the run loop is terminated by throwing an exception. Is this really the best way to do it? I would think setting a flag to terminate the loop would be better. I also noticed if you aren't using GameWindow.Run but a custom run loop, then this exception is difficult to deal with, because the exception itself is not public, so you have to catch a base exception and either deal with, swallow, or rethrow exceptions that are of a different type.
Well, let me know what you think. If there are coding style / naming issues, let me know and I will fix them.
Re: OpenTK Mac OS X support.
Oh, one other thing I wanted to ask. Is there support for the type of event handling where the user clicks the close box, and the program asks if they want to save before quitting (or something like that). I already have support for this sort of thing written into the carbon wrapper, so that it can cancel a window close event if the program / user input requires it.
Re: OpenTK Mac OS X support.
Fantastic work kanato!
Re: OpenTK Mac OS X support.
I just ran the GLSL example, and it gives an error message about requiring OpenGL 2.0 and says it will abort, but then it runs anyway. Looking at the extensions supported by my card, I see things like:
gl_apple_vertex_program_evaluators
gl_arb_fragment_program
gl_arb_fragment_shader
gl_arb_shader_objects
gl_arb_shading_language_100
gl_arb_vertex_program
gl_arb_vertex_shader
gl_version_1_1
gl_version_1_2
but no other gl_versions are listed.
And my the OpenGL driver info listed is
Intel GMA 950 OpenGL Engine, Intel Inc., 1.2 APPLE-1.4.56
So shaders are supported, even though I don't have higher than OpenGL 1.2 ?
Re: OpenTK Mac OS X support.
Ok, just one more thing for today, then I will wait for responses :P
I have mapped the OpenAL dlls to their OSX equivalents, but I know nothing about OpenAL. Are there any example programs which use OpenTK with OpenAL that I can test out? If I run the Example launcher and run AudioContext Test four times in a row, this is the output I see:
I don't know if that's good or not. And it's strange that the output changes after the first two runs.
Re: OpenTK Mac OS X support.
Great work! I won't have time to review the code for another 24 hours or so, but I can respond to your questions :)
[MacOS vs OSX]
No problem, MacOS looks better too.
[Font artifacts]
This has to do with sampling/texture coordinates, it happens on some cards/drivers but not on others. I'll loosen the packing by 1 pixel - this should take care of these artifacts.
[GLU tesselate]
This looks like a Mono problem (doesn't work on Linux either), but I haven't bothered to investigate yet. I'm looking for a managed alternative - if one exists, I'll be happy to see GLU go away.
[Window close event]
The implementation is a bit hairy. There are three ways to close the window:
GameWindow.Exit. This terminates the main loop. Then the Unload event is fired, the context is disposed andINativeGLWindow.DestroyWindow()is called. Finally, all pending events are processed untilGameWindow.Existsbecomes false.INativeGLWindow.ProcessEventsdetects this and raises theINativeGLWindow.Destroyevent, which is handled byGameWindow.glWindow_Destroy.GameWindow.glWindow_DestroyvallsGameWindow.Exitand the rest work out as above.GameWindow.Dispose. This callsGraphicsContext.DisposeandINativeGLWindow.Dispose, but I haven't worked out the details yet (presumably it should callGameWindow.Exitinstead).[Window resize event]
GL.Viewportgenerally belongs to aGameWindow.Resizeevent handler. As long as OnResizeInternal is called, the resize event will be raised.(The On*Internal methods will potentially perform some bookkeeping before raising the actual events. They also make sure that things will work correctly if the user overrides the On* methods - e.g. OnUpdate - and forgets to call
base.OnUpdate).[Class factory for platforms]
I was planning to do this, but I didn't think a MacOS port would become reality so soon. :)
I think you have such a system in place for AgateLib? I'd be very interested in such an implementation.
[GameWindowExitException]
It is the only way (I know of) to stop the main loop asynchronously. I.e:
Exit() must stop control before it reaches the "use opengl 2.0" line (otherwise it will crash!). To the best of my knowledge, an exception is the only method to achieve this.
I added this exception very reluctantly, but I really cannot see a better way.
If you have a custom main loop, the solution is simple: don't call Exit() (Exit() is specific to the Run() method - should document this better). Since you have control over the main loop, you are free to use a flag (or any other method you can think of).
[Exit event with cancel support]
I'm planning to add this, so this code is useful.
[GLSL]
Intel GMA 950 OpenGL Engine, Intel Inc., 1.2 APPLE-1.4.56
OpenTK reports the version from GL.GetString(): "1.2 APPLE-1.4.56" - I don't know if there's a better way.
I'll update the app to test for GLSL support explicitly, instead of relying on gl_version_2_0 being available.
[OpenAL]
This doesn't look very good. The attributes look bogus - they should contain things like frequency (44100) etc. At least it doesn't crash :)
I'm still working on
AudioContext. Should have a couple of examples ready later today, that test audio playback and audio effects.Re: OpenTK Mac OS X support.
Ok, I figured out the closing and resize events issues. In AGL, when a window is resized, aglUpdateContext needs to be called on the context. It looks like inorder to do that, either IGraphicsContext or IGraphicsContextInternal needs to have an Update method. The only other way I see to do it would be to expose the implementation of GraphicsContext, at least internally.
I guess I was a bit thrown off with the close event integration because if you're running your own event loop there is no event that is raised when the native window is closed. But that can be resolved easily by making GameWindow.ExitInternal call an event. I'll submit a patch for that later.