MonoGame-SDL2 #2031

wants to merge 29 commits into


None yet

This is MonoGame-SDL2, a new MonoGame desktop platform that uses SDL2 as its base platform library.

The details of this pull request have been organized as follows:

  • 1: Platform Support
  • 2: Libraries
  • 3: About the SDL2_GameWindow
  • 4: About the SDL2 Event Loop
  • 5: About the SDL2_GamePad
  • 6: About Song and Video playback
  • 7: Example Titles
  • 8: Third-Party Contributors

MonoGame-SDL2 currently "officially" supports Windows, Mac OSX and GNU/Linux. However, MG-SDL2 platform support is wholly dependent on an operating system's native support for Mono, SDL2 and OpenAL. If an operating system supports these three libraries, then MonoGame-SDL2 is expected to work there. This adds the possibility of supporting more platforms, such as FreeBSD, Haiku, and other SDL2-supported platforms.

To more easily support distributing MonoGame-SDL2 titles on the Mac, MonoKickstart has been updated to support 32- and 64-bit OSX (Snow Leopard 10.6.8 or higher). Without the burden of MonoMac, it is now possible to create and distribute 64-bit Mac OSX MonoGame titles.

All platform code is determined at runtime. This means that a single set of MonoGame-SDL2 assemblies is expected to work on all target platforms without recompilation. The notable exception is potential incompatibilities with output from the .NET/Mono compilers against the .NET/Mono runtimes (for instance, .NET assemblies on the Mono runtime).

MonoGame-SDL2 depends on SDL2# and TheoraPlay#. At the native level, MonoGame-SDL2 requires the following native libraries:

If you do not use Song/Video playback, those additional libraries are NOT required. If you do not use Video playback, you can even ignore TheoraPlay# when packaging your game.

Windows and Linux do NOT use OpenTK, and OSX does NOT use MonoMac. However, we use the OpenTK OpenGL and OpenAL bindings, which are currently bundled in SDL2# as "MiniTK".

Additionally, because we use SDL2#, we no longer depend on Tao.Sdl on the desktop.

3: ABOUT THE SDL2 GameWindow
MonoGame-SDL2's GameWindow is notable for its behavior with regard to display management, particularly in fullscreen mode.

A common problem with OpenTK, and cross-platform display management in general, is that fullscreen modes are very inconsistent in behavior and are incredibly volatile, particularly on Linux and in several situations on OSX (most notably Retina Displays). To resolve this, SDL2 includes a feature called "SDL_WINDOW_FULLSCREEN_DESKTOP", which will always set the fullscreen resolution at the resolution set by the operating system's desktop environment. So, if your desktop is set to 1920x1200, SDL_WINDOW_FULLSCREEN_DESKTOP will always set the fullscreen resolution to 1920x1200.

In combination with SDL_WINDOW_FULLSCREEN_DESKTOP, SDL2_GameWindow uses an internal framebuffer object to act as the "backbuffer", which retains the actual desired resolution. Upon calling SwapBuffers, we blit the framebuffer to the backbuffer, scaling the image to the desktop resolution if needed. Mouse cursor positions are also scaled when necessary, for the sake of accuracy.

On top of resolving the issue of fullscreen instability, it also allows MonoGame developers to set the depth-stencil attachment of "backbuffer", something that was previously not possible without trashing the OpenGL context.

When querying your game's current resolution, it is strongly recommended that you use GraphicsAdapter.CurrentDisplayMode, as SDL2_GameWindow.ClientBounds will give you the SDL2 window resolution, which may be different than the resolution in fullscreen mode. Both have their usefulness, but for portability and accuracy purposes, the GraphicsAdapter is given the "intended" resolution, while the SDL2_GameWindow has been given the info based on its platform-specific behavior, per the XNA4 specification.

The SDL2_GameWindow's Handle property will return the SDL_Window* IntPtr, so rather than using System.Windows.Forms, you should use SDL2# when directly modifying the GameWindow on MG-SDL2.

For window icons, we attempt to load a BMP file that is the name of the window. For example, naming the window "FEZ" will attempt to load "FEZ.bmp" as the window icon.

Rather than using callbacks, the SDL2 platform polls events pumped by the SwapBuffers call. The event loop can be found here:

This simplifies event tracking as well as maintenance of various events. For example, controller hotplugging support can be added simply by adding the DEVICE events to this loop.

The GamePad support has been completely rewritten to drastically improve controller support.

At the same time, MonoGame-SDL2 both improves configurability of controller support as well as automating configuration of controllers for MonoGame titles.

SDL2 has a subsystem called "SDL_GameController", a system added by Alfred Reynolds at Valve Software. When a joystick is recognized by SDL2 as a GameController, the device is automatically configured around the Xbox 360 controller format. Within SDL2 itself, Xbox 360 controllers, PS3 controllers and various Logitech controllers are automatically supported, but GameController bindings can be found from outside of libSDL2 itself. For example, if an SDL2 title is run via Steam, SDL2 will obtain controller configurations from Steam Big Picture Mode, so any controller that has been run through Steam Big Picture will automatically be configured for a MonoGame-SDL2 title. This feature is of significant importance for SteamOS in particular.

In situations where a joystick is NOT supported by SDL_GameController, users can configure joysticks with the MonoGameJoystick.cfg configuration file. This has been documented on the PCGamingWiki:

Another new addition to MonoGame is support for controller vibration. SDL2 not only provides haptic support, but provides left/right motor support where supported. Currently, Windows and Linux support left/right vibration, while OSX does not. In situations where the haptic device does not support left/right vibration, we simply run a simple sine wave vibration using the left/right strengths.

As of September 30, MonoGame-SDL2 also supports gamepad hotplugging, via SDL2 joystick device events.

MonoGame-SDL2 uses SDL2_mixer for Song playback. We automatically look for FLAC and Ogg Vorbis by default, but any format that SDL2_mixer supports is expected to run on MonoGame-SDL2. mp3 support is NOT checked for by default, primarily due to patent/licensing concerns.

MonoGame-SDL2 contains a brand new VideoPlayer based on TheoraPlay#. Rather than using Windows Media Video, MG-SDL2 reads in Ogg Theora video data.

Audio is streamed into OpenAL, and video can be streamed either via software rendering or via OpenGL acceleration. For MonoGame-SDL2, we use the YUV->RGBA OpenGL acceleration by default.

Since SDL2# development began in April of this year, MonoGame-SDL2 has shipped in nearly a dozen commercial titles across multiple promotions, including the Humble Indie Bundle, and most of them were among the first to ship on Valve's new SteamOS.

Some games currently using MonoGame-SDL2 are...

Escape Goat:
Soulcaster I/II:
A Virus Named TOM:
Rogue Legacy:
Dust: An Elysian Tail:
Blueberry Garden:

The following developers were involved in the development of MonoGame-SDL2, and have been CC'd into this thread, with their related attributions.

  • @sulix - General MonoGame-SDL2 development/design/bugfixing, Humble QA
  • @khbecker - VideoPlayer bugfixing, Humble QA
  • @xanather - TextInputEvent support for MonoGame-SDL2
@espes espes and 4 others commented on an outdated diff Sep 25, 2013
@@ -467,6 +467,37 @@ internal static string StorageRoot
get {
return ApplicationData.Current.LocalFolder.Path;
+#elif SDL2
+ if (Environment.OSVersion.Platform == PlatformID.Win32NT)
+ {
+ return Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
+ }
+ if (Environment.OSVersion.Platform == PlatformID.MacOSX || Directory.Exists("/Users/"))
espes Sep 25, 2013

Unix platforms that happen to have "/Users"? Is the extra condition really needed?

flibitijibibo Sep 25, 2013

In some cases, Mono applications on OSX will report the Platform as Unix rather than MacOSX. Luckily, the quickest way to tell OSX from standard Unix is to check for /Users/, since the actual Unix standard is /home/.

flibitijibibo Sep 25, 2013

I'll check this out, thanks for the link.

A part of me wonders if we could have this internally in MonoGame somewhere as a static variable (internal enum OSPlatform)? Being able to have a consistent way to check platform dynamically would be wonderful, and would prevent a lot of copypasta'd checks like these.

dellis1972 Sep 25, 2013

@flibitijibibo yup, this kind of platform check should go in utilities class somewhere I think or be available as an internal static member of the GamePlatform base class perhaps?

flibitijibibo Sep 25, 2013

I'll let the core team decide, since it'll affect more than just SDL2. I'll implement it as soon as everyone who wants to chime in on that has done so. The two major points would be where to put it, and what enum values would be used (for instance, would WinDX be separate from WinGL/WinSDL2, or would WinDesktop be enough?).

KonajuGames Sep 25, 2013

This is really a Mono bug that should get fixed by Xamarin. If Environment.OSVersion.Platform is reporting the wrong value, report it to Xamarin.

mhutch Sep 28, 2013

Mono's behavior is intentional. By the time PlatformID.MacOSX was introduced in .NET 2.0 SP2, too much code depended on the existing behavior. For more info, see:

The most reliable way I know of is to P/Invoke uname and check for "Darwin".

flibitijibibo Sep 28, 2013

o_o "Hacktastic" is right...

Well, I guess this makes another case for having an internal static Platform value somewhere in the code...

@espes espes and 1 other commented on an outdated diff Sep 25, 2013
+ if (INTERNAL_haptics[x] != IntPtr.Zero)
+ {
+ if (SDL.SDL_HapticEffectSupported(INTERNAL_haptics[x], ref INTERNAL_effect) == 1)
+ {
+ SDL.SDL_HapticNewEffect(INTERNAL_haptics[x], ref INTERNAL_effect);
+ }
+ else if (SDL.SDL_HapticRumbleSupported(INTERNAL_haptics[x]) == 1)
+ {
+ SDL.SDL_HapticRumbleInit(INTERNAL_haptics[x]);
+ }
+ }
+ // Check for an SDL_GameController configuration first!
+ if (SDL.SDL_IsGameController(x) == SDL.SDL_bool.SDL_TRUE)
+ {
+ System.Console.WriteLine(
espes Sep 25, 2013

s/Console.WriteLine/Debug.WriteLine/g ?

flibitijibibo Sep 25, 2013

This is actually intentional. I thought about putting this and the EXT_swap_control_tear bits into the GamePlatform.WriteToLog, but getting this information from customers has been super helpful in the past, so I kept it in stdout.


awesome :) Looking forward to digging into this PR :)


@flibitijibibo can you add a section to the script which (for Windows only) will build the SDL2 .sln. That way the build bot will be able to make sure it builds before we pull it in :)


@dellis1972 Oh, dear, I'm afraid I'm not familiar with how to add this to the script... I don't want to accidentally blow anything up and muck up the diffs! D:

Is this correct?

MonoGame member

Can one of the admins verify this patch?

MonoGame member

Can one of the admins verify this patch?


@flibitijibibo looks fine :) you are now officially a nant script expert ;)


once that is in , I'll kick off the build bot


Aaand it's pushed!

/me crosses fingers


@flibitijibibo looks like the build passed. Should the SDL2.dll's have a # on the end?


@dellis1972 Yup, the managed libs have SDL2#.dll and SDL2#.dll.config, and TheoraPlay# is the same story. Did the build bot freak out over those? o_o


@flibitijibibo nope it didn't which is cool. Just wasn't expecting the # at the end. ;)

OK so the build looks good (once the build bot decides to update the PR). We'll need to have a few reviews from some of the other core team, but its looking good. Great work, If we can get some templates sorted for VS and XS this can probably be included in the 3.2 release which is what we are gearing up for now.

If someone has time a step by step guide on using KickStarter to create packages for Mac and Linux would be fantastic.. any takers ?


I do sooortakinda have a few words on making the Kickstart bundle in the new MonoKickstart README, but it's not much:

Of course, that doesn't address things like Mac app bundles (read: how I maek folders and icns) and MojoSetup packages... Most of the time I just tell people to rip off of my games shamelessly and go from there. :P

I'm shipping some new things throughout the next couple weeks, so I may not be able to write a nice tutorial on this for a while... I really wish I had automated that process.


@espes!! You've been away for so long. Welcome back!


@flibitijibibo Thanks for the detailed PR header. Greatly appreciated in getting our heads round the amount of work you've but into submitting this.

MonoGame member

Test PASSed.
Refer to this link for build results:

MonoGame member

Before i dive into this PR further... i think we should decide if we should merge #2030 for JSIL support first.


I'd be alright with JSIL getting merged first. Luckily the only real conflict between the two is the Unsafe.cs section; everything else seems to be separate. May need to rope @kg in here as well.

MonoGame member

Luckily the only real conflict between the two is the Unsafe.cs section

Yea... i don't off hand see any conflicts. The fact MiniTK has an identical API to OpenTK means it won't affect the JSIL work.


Upon the request of some of my clients, I ended up adding hotplugging support to MG-SDL2:


Note that this is NOT in the pull request yet, it is only in my MG-SDL2 development branch. I'll only be adding this in once I've verified it on all platforms (so far, only Linux and OSX, need a few more Windows cases aside from one 360 controller...).

If we're itching to have this feature in, then feel free to delay this merge... gives more time to merge JSIL in before this, anyway.


The MG-SDL2 pull request has just been updated to add hotplugging support. Also included is an SDL2# update, which should not affect this project directly.


I love it! The window finally respects my PreferredBackBufferWidth/Height settings and doesn't revert, unlike that awful OpenTK.

I thought I'd note, though a few things:

  • Game.Window.AllowUserResizing is forced to be false. I personally don't use that and think a user should never resize a game's window, but I just thought I'd mention it.
  • The game runs with more average CPU usage than with OpenTK. It doesn't seem to have worse performance.
  • Resizing the PreferredBackBufferHeight/Width in the middle of the game has quite unusual consequences. All Texture2D's appear to become white squares, and the window refreshes from black in a different position on the screen.
  • EDIT: GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Width seems to return the width of the window (e.g. 800) in this SDL port, while it returns the proper width of the screen in the OpenTK version (e.g. 1920). This applies for the Height as well, of course. This can be a big problem for trying to automatically set the framebuffer PreferredBackBufferHeight/Width to match the screen resolution.

All of these are just fine, and quite avoidable (with the exception of the fourth), but for testing it should probably be mentioned.
All of these tests are on Ubuntu 13.04 with libsdl 2.0.0 installed - I can't vouch for any other platforms.




Can you try this patch for me?


The pull request has been updated for the DisplayMode patch. CC: @kupiakos


@flibitijibibo I hope you don't mind but once this gets pulled in , we will probably fork the dependent libraries into the Mono-Game account. This is so you can continue to make updates and changes without worrying about breaking the "stable" monogame.


As long as the libraries get updated frequently, shouldn't be too much of a problem.

Also, I'm almost entirely sure that this test will fail; haven't pulled from upstream yet since I wasn't sure when this was going to be pulled... didn't want to clutter the Git history with needless merges.


Actually, quick question: is there a reason the develop repo wouldn't just stick with the Git revision found in ThirdParty, rather than clone a repo with that revision? For instance, updates to SDL2# wouldn't affect it, and when updates are needed, you can just git pull origin master and get MonoGame updated to the latest SDL2#.

I only ask because I wonder what it'll be like when we have to update SDL2# for some reason (SDL2 2.1, some generic SDL2# bugfix, etc). I'd like to keep the number of branches to a bare minimum, as needless forking is always asking for trouble (but if there's a good reason, then :shrug: ).


Yeah, I'll be tagging releases for both TheoraPlay# and SDL2# by the end of this year.

I'll probably stamp TheoraPlay# as 1.0 when my last port using Video ships (should be sooner than later).

At the same time I'll stamp RC1 on SDL2#, and the only difference between RC1 and 1.0 will be adding XML docs, so the API will remain as-is. Releases after that will just be updating for each SDL2 release, with minor releases for SDL2#-specific patches.


The pull request has just been updated with an accuracy fix. For the initial window creation, we now use GraphicsDeviceManager's DefaultWidth and DefaultHeight.

MonoGame member

Test FAILed.
Refer to this link for build results:


Will probably have to do a merge from upstream before this will build again. Let's revisit this once the team is ready to actually merge this, to avoid muddling with the Git history.


Is there a ETA on the merge for this PR? MonoGame-SDL should be a part of MonoGame! It provides so many benefits at zero losses for the general MonoGame/XNA desktop platform programmer compared to the current WinGL implementation. The moment I found MonoGame-SDL I became in love with it as it suited my needs VERY well. The quicker it gets merged the more stable and ideal framework MonoGame will become.

WinGL - not cross platform (its not...)
Monogame-SDL - cross platform!


In addition to the JSIL project, I'd also like to wait and see how these two turn out:


They'll be closely related to the MG-SDL2 FBO, 1944 in particular.

@jwosty jwosty referenced this pull request Oct 21, 2013

Fixed Issue #1614 #2101


The pull request has been updated for SDL2 2.0.1 (for us, just an SDL2# update).

Patch notes for SDL2 2.0.1 are here:

Highlights include SRGB framebuffer support, retina HIGHDPI support, and some additional APIs such as SDL_filesystem.h and SDL_GetSytemRAM().


The pull request has been updated to use SDL_GetPlatform() for platform detection, rather than Environment.OSVersion.Platform.

The value is stored in SDL2_GamePlatform as public static readonly string OSVersion, so it can be read anywhere within MonoGame as well as projects that are willing to depend specifically on MG-SDL2's GamePlatform for simplified platform detection. For OSX in particular, this is significantly more reliable than Mono's OSVersion.Platform variable.


The pull request has been updated with SDL2#/TheoraPlay# updates that change their project/assembly names. This should fix use of the MG-SDL2 project on VS2012/VS2013 setups.


Wow, this PR sounds a really great addition to Monogame! We were looking into non-standard Gamepad support and this Pull Request would save us the hassle of having to do the binding ourselves, and using the Big Picture config instead.

Any chance this can get merged anytime soon? :)


Sounds like it'll happen after 3.5 (?), so if you need it before then you can use MG-SDL2 upstream (this pull is incompatible with develop at the moment):


Thank you, we'll try and see how it goes :)


@mgbot test


This probably won't work just yet. Still need to pull from develop, let me know when you guys are ready to merge this in.


The pull request has been updated with some changes to improve XNA4 accuracy for the scissor test and scissor rectangle. Note that the RasterizerState has added a bool for checking whether or not the test is enabled; this is something that should be applied to just about every one of these GL calls, but to minimize unnecessary changes this is what we will stick with for this pull request.


I just merged back from develop for mg-sdl2-final. This should now be buildable and testable again. The diffs were starting to get super large, so it's probably time to shorten the gap a bit even if it bulks up the Git history at the end.


Updated again, just making sure the Test csproj stays up-to-date... forgot about one of the new tests added recently, on top of the PackedVector stuff that was merged today.


Updated one more time for develop, should still be buildable and usable.

Will likely start FNA development this weekend, so I wanted to give this one last push before I start ripping things up in MG-SDL2 upstream.

MonoGame member

@flibitijibibo - Thanks for the update!

So @KonajuGames and I looked this over and discussed our plans on how to merge it.

  1. I will be doing a MonoGame 3.2 release this week.
  2. Steve and I will test the SDL2 branch.
  3. We will make some changes to this PR.
  4. We will merge the SDL2 platform work into develop.
  5. A few weeks later we will purge the OpenTK-based desktop platforms.

This means a single desktop OpenGL platform project which depends on SDL2. Not only will this provide us a more reliable OpenGL desktop build, but will also let us remove a lot of code and #ifs in the code base.



Sounds cool. monogame-sdl2 has the work to remove a lot of the defs, mainly WINDOWS && OPENGL, MONOMAC and LINUX, if you want to poke around that when doing the TK purge.


Really looking forward to this, and will be testing on my ongoing Win/Mac/Nix project as soon as the merge happens. Will be great not to have to struggle with the OpenTK platforms any more!


Closing this today.

With the advent of FNA and the changes the MonoGame project is making to the platform management (which I love, by the way!), mg-sdl2-final has gotten in the uncomfortable position of not really being relevant to either branch. FNA's SDL2 platform has changed quite a bit, both for general accuracy fixes and for the OpenGLDevice that is now used to wrangle most of the GL calls. With the changes we'll be doing in the long run, the SDL2 platform will have a lot of fundamental differences with this one, and without anyone maintaining this, it'd just bloat up the MonoGame project. While I'm still fanboyishly driving OpenTK out of FNA, at least now there's someone to maintain that library while MonoGame is still using it.

At this point, it'd probably be easier for someone to just gank FNA's SDL2/ folder and merge it into MonoGame than it would be to merge this stuff. A shame, but if someone does end up doing that, I think you'll like what we've come up with since branching off into a new thing.

Thanks to the contributors and the project maintainers for their time. I'm sure FNA/MonoGame will stay pretty closely tied, but maybe not in this regard.

@flibitijibibo flibitijibibo deleted the flibitijibibo:mg-sdl2-final branch Apr 20, 2014
MonoGame member

Thanks @flibitijibibo.

We did fully intend to merge this, but lots of things changed over the last 2 months that complicated plans. If we find the need to move to SDL2 we will have to pull elements from your repo and fix things up in a brand new PR.

I still am I concerned with depending on OpenTK. Will issues get resolved? Will it continue to improve? Will development stall for years again? I hope things go well, but we can always fall back on your SDL work.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment