Cover photo
Ryan Gordon
Works at
Attended Queens University
Lives in Charlotte, NC
1,633 have him in circles


Ryan Gordon

Shared publicly  - 
Just pushed a change to SDL to make it cooperate with Spaces on Mac OS X.

If you have a resizable SDL window, it'll now give you the "go fullscreen" button on the titlebar, and it works how you'd expect. To the SDL app, it just looks like the window changed sizes, no different than if the user clicked Maximize or whatever, but the user has more power now.

Also: FULLSCREEN_DESKTOP windows now get their own Space. This is really great; you can play your game, swipe over to your desktop for a moment, see an animated thumbnail in Mission Control, etc. Previously it just took over your desktop and minimized the window when you switched applications.

(We still support the old behavior on older Mac OS X versions that didn't have Spaces.)

This is more reason to stop using SDL_WINDOW_FULLSCREEN. If you can, you should be using SDL_WINDOW_FULLSCREEN_DESKTOP and adjusting for whatever resolution you get. It makes for a better end-user experience for many reasons, and today there's one more reason.

We're going to shake bugs out of these changes as fast as possible and ship it in SDL 2.0.2.﻿
Ryan Gordon's profile photoEthan Lee's profile photoBastien Nocera's profile photoDavid Poole's profile photo
Thanks for merging it :)﻿
Add a comment...

Ryan Gordon

Shared publicly  - 

I've just pushed an interesting change to SDL, but to explain what it is, it's useful to know the problem we were trying to solve.

- The Steam Runtime has (at least in theory) a really kick-ass build of SDL2, but developers are shipping their own SDL2 with individual Steam games--including me. These games might stop getting updates, but a newer SDL2 (with, say, Wayland support, which we'll be shipping in 2.0.2) might be needed later. Certainly we'll always be fixing bugs in SDL, even if a new video target isn't ever needed, and these fixes won't make it to a game shipping its own SDL.
- Even if we replace the SDL2 in those games with a compatible one, that is to say, edit a developer's Steam depot (yuck!), there are developers that are statically linking SDL2 that we can't do this for. We can't even force the dynamic loader to ignore their SDL2 in this case, of course.
- If you don't ship an SDL2 with the game in some form, people that disabled the Steam Runtime, or just tried to run the game from the command line instead of Steam might find themselves unable to run the game, due to a missing dependency.
- If you want to ship on non-Steam platforms like GOG or Humble Bundle, or target generic Linux boxes that may or may not have SDL2 installed, you have to ship the library or risk a total failure to launch. So now, you might have to have a non-Steam build plus a Steam build (that is, one with and one without SDL2 included), which is inconvenient if you could have had one universal build that works everywhere.
- We like the zlib license, but the biggest complaint from the open source community about the license change is the static linking. The LGPL forced this as a legal, not technical issue, but zlib doesn't care. Even those that aren't concerned about the GNU freedoms found themselves solving the same problems: swapping in a newer SDL to an older game often times can save the day. Static linking stops this dead.

So here's what we did:

SDL now has, internally, a table of function pointers. So, this is what SDL_Init now looks like:

    UInt32 SDL_Init(Uint32 flags)
        return jump_table.SDL_Init(flags);

Except that is all done with a bunch of macro magic so we don't have to maintain every one of these.

What is jump_table.SDL_init()? Eventually, that's a function pointer of the real SDL_Init() that you've been calling all this time. But at startup, it looks more like this:

    Uint32 SDL_Init_DEFAULT(Uint32 flags)
        return jump_table.SDL_Init(flags);

SDL_InitDynamicAPI() fills in jump_table with all the actual SDL function pointers, which means that this _DEFAULT function never gets called again. First call to any SDL function sets the whole thing up.

So you might be asking, what was the value in that? Isn't this what the operating system's dynamic loader was supposed to do for us? Yes, but now we've got this level of indirection, we can do things like this:

    export SDL_DYNAMIC_API=/my/actual/

And now, this game that is staticallly linked to SDL, can still be overridden with a newer, or better, SDL. The statically linked one will only be used as far as calling into the jump table in this case. But in cases where no override is desired, the statically linked version will provide its own jump table, and everyone is happy.

So now:
- Developers can statically link SDL, and users can still replace it. (We'd still rather you ship a shared library, though!)
- Developers can ship an SDL with their game, Valve can override it for, say, new features on SteamOS, or distros can override it for their own needs, but it'll also just work in the default case.
- Developers can ship the same package to everyone (Humble Bundle, GOG, etc), and it'll do the right thing.
- End users (and Valve) can update a game's SDL in almost any case, to keep abandoned games running on newer platforms.
- Everyone develops with SDL exactly as they have been doing all along. Same headers, same ABI. Just get the latest version to enable this magic.

A little more about SDL_InitDynamicAPI():

Internally, InitAPI does some locking to make sure everything waits until a single thread initializes everything (although even SDL_CreateThread() goes through here before spinning a thread, too), and then decides if it should use an external SDL library. If not, it sets up the jump table using the current SDL's function pointers (which might be statically linked into a program, or in a shared library of its own). If so, it loads that library and looks for and calls a single function:

    SInt32 SDL_DYNAPI_entry(Uint32 version, void *table, Uint32 tablesize);

That function takes a version number (more on that in a moment), the address of the jump table, and the size, in bytes, of the table. Now, we've got policy here: this table's layout never changes; new stuff gets added to the end. Therefore SDL_DYNAPI_entry() knows that it can provide all the needed functions if tablesize <= sizeof its own jump table. If tablesize is bigger (say, SDL 2.0.4 is trying to load SDL 2.0.3), then we know to abort, but if it's smaller, we know we can provide the entire API that the caller needs.

The version variable is a failsafe switch. Right now it's always 1. This number changes when there are major API changes (so we know if the tablesize might be smaller, or entries in it have changed). Right now SDL_DYNAPI_entry gives up if the version doesn't match, but it's not inconceivable to have a small dispatch library that only supplies this one function and loads different, otherwise-incompatible SDL libraries and has the right one initialize the jump table based on the version. For something that must generically catch lots of different versions of SDL over time, like the Steam Client, this isn't a bad option.

Finally, I'm sure some people are reading this and thinking "I don't want that overhead in my project!"  To which I would point out that the extra function call through the jump table probably wouldn't even show up in a profile, but lucky you: this can all be disabled. You can build SDL without this if you absolutely must, but we would encourage you not to do that. However, on heavily locked down platforms like iOS, or maybe when debugging,  it makes sense to disable it. The way this is designed in SDL, you just have to change one #define, and the entire system vaporizes out, and SDL functions exactly like it always did. Most of it is macro magic, so the system is contained to one C file and a few headers. However, this is on by default and you have to edit a header file to turn it off. Our hopes is that if we make it easy to disable, but not too easy, everyone will ultimately be able to get what they want, but we've gently nudged everyone towards what we think is the best solution.

Here are most of the changes for the Dynamic API:

James Lomax's profile photoMatteo De Carlo's profile photoJason Dagit's profile photoC.W. Betts's profile photo
+Clément DAVID OS X does not use ELF: it uses Mach-0. To my knowledge, OS X is the only modern UNIX or UNIX-like that does not use ELF. Although you can mess with the dynamic linking names, there's always a possibility that SDL2.framework won't be installed in either /Library/Frameworks or ~/Library/Frameworks. And said version might be out-of-date itself. Yeah, OS X doesn't have a good native package management built-into it: developers have to work around it.

Not to mention Windows, which uses something quite archaic in comparison of the other two binary formats (I'm pretty sure it supports Pascal symbol linking. Not even OS X/Darwin has that). C.F. "DLL Hell."﻿
Add a comment...
Jimmie Johnson wins the NASCAR race, climbs on top of his logo-covered car, next to a giant cardboard Sprint cellphone, sprays the crowd with Gatorade, and reminds everyone in his victory speech to shop at Lowes tomorrow.

And all my web-savvy friends are all like "who clicks on ads on the Internet?"

I suspect there's some overlap in viewership.﻿
Michael Monn's profile photoRyan Gordon's profile photoTimothee Besset's profile photoJan Moren's profile photo
+Timothee Besset Visiting in-laws watching the race. :)﻿
Add a comment...

Ryan Gordon

Shared publicly  - 
So there's a massive Mac/Linux update for Super Meat Boy, just in time for it to be 80% off on Steam:

Here's the rundown of new stuff.

- Linux version now available on Steam. If you already own the game for Windows or Mac on Steam, you get the Linux version for free right now. Otherwise, your three dollars gets you three platforms of Super Meat Boy, plus SteamOS support some day.
- Now using SDL2, which means...
- controller support that actually works!
- Tons of bug fixes.
- Super Meat World now works on Linux.
- 64-bit support on Mac OS X.
- Steamworks support on Linux (32-bit only, not my fault!)
- Fullscreen support on Mac OS X.
- Better fullscreen support on Linux.
- Mac framerate should be dramatically better.

Updated Humble Bundle builds coming soon, but I'll probably wait a day or two for Steam feedback before packaging it up.

Please be gentle: a lot of code changed, as part of this work was smashing Tommy's Mac port and my Linux port together and fixing things up from there. If you find bugs, please report them at and I'll try to sort them out asap.﻿
Janne Sinisalo's profile photoDima Braun's profile photoAnıl Özbek's profile photoRyan Gordon's profile photo
Bah. :( Oh well. At least it won't be lost again in the future. Thanks Ryan!﻿
Add a comment...

Ryan Gordon

Shared publicly  - 
Meanwhile, this very minute, old Jessie McVey the well digger--no one knows how old he is, lived in that county all his life--is sitting at the bar of the National Hotel this very minute, looking at the freaks out in the street and muttering under his breath: "No matter how New Age you get, old age gon' kick yo' ass."﻿
Add a comment...

Ryan Gordon

Shared publicly  - 
I swear writing long, rambling blogs about SDL is not my full-time job, but there's a lot to cover, so here's one last post about it for now.

Back around the dawn of time, when we were planning to branch off for SDL 1.3, as it was called before the ancient Greeks invented integer two, we decided to make promises^W^Wwrite a roadmap for where we wanted the project to go next.

The original plan ended up here, literally in my .plan file:

(...and history is a big ball of wibbly wobbly timey wimey stuff. The first commit to the SDL-1.3 branch was a year and a half earlier: April 27th, 2006.)

So how did we do?

Overall, pretty well. We hit much of this list, and added tons of things we hadn't even dreamed of at the time (like the brilliant Game Controller API, or Thread Local Storage support, or power status or GLES or SDL_assert, or hell, anything to do with phones).

Some of the bigger stumbling points were in the audio subsystem, which were my fault: I rewrote almost the entire thing and was careful to keep the 1.2 API intact, but didn't get a whole bunch of important things in there, like 7.1 audio, or hell, audio recording. They're all still planned for a future version. Interestingly, SDL's resampler is still totally busted if you aren't converting between multiples (so 11025Hz to 44100Hz? No problem. But 48000Hz? Buffer overflow.), but pretty much every modern audio API will give you whatever you ask for and convert/resample on your behalf, so this is actually much less important than it used to be, believe it or not.

Also worth noting: I thought my perl script to generate audio data converters was brilliant, since we could do just about anything in one pass over the data with the final C code it spit out. Turns out there's so many variations, though, that we've basically stuffed the library full of tons of code you'll never use. That's going away at some point. It works, but at this point, it'd be better to shrink the library and try to work with SIMD instructions in a cache-friendly way, which would have been faster in the first place, too. Live and learn, best intentions, bygones, blah blah blah.

The biggest request I get, from all over the Internet, is the multiple mouse support, which is notably absent in 2.0.0. We originally had a Google Summer of Code student that we asked to merge ManyMouse ( ) into SDL, but he went off and did his own thing and it just didn't work out, so we yanked it. This will be coming in a future release. ManyMouse still works alongside SDL2 in the meantime.

So, okay, what's next?

Here's the start of the next roadmap. I'll be migrating this to the wiki sooner or later. It's not a promise of anything, it's just things we'd like to look into, and maybe do. Comments, complaints, suggestions, and requests are all welcome.

Maybe we'll all be chuckling at this post in 2021, like we do that .plan file for SDL 1.3, when we still haven't shipped SDL 2.1 yet. Fortunately, Google will probably have cancelled this service by then and I'll be saved the embarrassment.

Hopefully Google+ won't mangle this list too badly.

API/ABI BREAKING THINGS (goes in SDL 3.0.0+)...

- Add SDL_HAPTIC_SQUARE back in. We need more than 16 bits for new force-feedback effects, and we killed this one at the last minute to add SDL_HAPTIC_LEFTRIGHT, to expose the exact functionality of Microsoft XInput for all those X360 controllers on Windows.

- Finally retire KMOD_*? It drives me nuts that these don't have an "SDL_" in front of them.

- AUDIO_* should be SDL_AUDIO_. Same as the KMOD_ problem.

- Why do we have SDL_Init() and SDL_InitSubSystem()? Maybe remove one of these?

- Why do we have SDL_AudioQuit(), etc, and also SDL_QuitSubSystem()? Maybe remove one of these.

- SDL_OpenAudioDevice's "iscapture" should be an SDL_bool.

- Remove SDL_OpenAudio() and only allow SDL_OpenAudioDevice(). Actually remove the compatibility code for the 1.2 audio API.

- Should we remove the window parameter from SDL_GL_SwapWindow()? Maybe require it to swap the current context, regardless of window? We can't make sense of how this should work across every platform.

- Since SDL_free() is now a real symbol, let's get rid of SDL_FreeWAV().

- SDL_assert_data should be SDL_AssertData.

- Make SDL_GetTicks() 64 bit?

- Add a formal event struct for SDL_QUIT that enumerates ways the event was generated (destroyed last window, Apple-Q, SIGINT, etc).

- Change SDL_TouchID to SDL_TouchDeviceID? It's easy to confuse with the fingerID right now.

- Remove joystick balls? There's been like one joystick, ever, that used this, and it was from 1998.

- Joystick API reworking (motion controllers? guitar hero controller things? Wiimotes and Move and Kinect? no buttons only axes, etc)

- Add a version of SDL_AddTimer() that gets processed on the main thread in the event loop - maybe just add a timer event and timer ID parameter?

- Constify everything.

- Remove SDL_GetWindowSurface() from the public API? Let the software renderer access it, and not applications?


- Audio recording (microphones)

- Video capture (webcams)

- Locale API (Find out user is in the "en_US" locale, etc).

- Reintroduce multiple mice

- Multikeyboard?

- An API to fill out app data (for the Mac About box, defaults for PulseAudio, etc).

- An API to name the output on the audio device (for PulseAudio).

- SDL_CreateRendererByName() convenience function.

- Audio device disconnect notification (query and event).

- Move+Resize windows in one API call.

- Add an SDL_DEPRECATED define, start deprecating things.

- sRGB GL context support

STUFF THAT CAN CHANGE WHENEVER (refactoring, new targets, etc (SDL 2.1.0+ or SDL 2.0.1+)...

- Wayland support

- Mir support

- Raspberry Pi support

- Merge all the EGL targets into one backend with a few #ifdefs or something

- 7.1 audio support

- Add Linux /dev/input support for Raspberry Pi mouse/keyboard without X11?

- PS4 port? How indie-friendly is Sony actually going to be?   :)

- Replace win32 KEYDOWN/KEYUP with RAWINPUT?

- Rewrite the audio loop (fix resampling, improve converting, etc).

- Throw out the audio converter perl script, do something that sucks less.

- Try to unify all the dynamic loading code all over the place.

- Look for FIXMEs

- Move from Xlib to xcb?

- SDL_WINDOWPOS_UNDEFINED and SDL_WINDOWPOS_CENTERED do the same thing internally. Extend the backend to allow the window manager to really handle SDL_WINDOWPOS_UNDEFINED?

- Make various renderers support more than SDL_PIXELFORMAT_ARGB8888

- udev support for audio device connect/disconnect

- I really hate the audio conversion API. It's way too complicated to explain well.

- Should SDL_RWFromFP() always take a void*, removing the #ifdef ?

- Is left/right/middle/x1/x2 still all the mouse buttons we should support?

INFRASTRUCTURE (non-code stuff)...

- Update Bugzilla to 4.4 or whatever

- Maybe replace Bugzilla with something else?

- Get Markdown support on

- Replace buildbot with Jeeves or something?

- Migrate buildbots elsewhere so Ryan can reboot his workstation occasionally?  :)

- Make documentation easier to ship offline?﻿
Ryan Gordon's profile photoYing Chiong's profile photoNehemiah Dacres's profile photoNathaniel Fries's profile photo
Why? I didn't complain that ManyMouse is not integrated.﻿
Add a comment...
Have him in circles
1,633 people

Ryan Gordon

Shared publicly  - 
Videos for my Steam Dev Days talks are posted!

SDL2 talk: Game Development with SDL 2.0
Linux talk: Getting Started with Linux Game Development﻿
Susan Stabley's profile photoErik Yuzwa's profile photoErick Powers's profile photoKimmo Merikivi's profile photo
And just after you debunked the distribution fragmentation myth in Steam dev days, CD Projekt made this uninformed statement:

Hopefully correct information reaches their ears. The video has been linked in The Witcher forums, at least.﻿
Add a comment...

Ryan Gordon

Shared publicly  - 
My minor Christmas gift:

I love 1Password ( ), but it's a Mac and iOS app, mostly. There's a web interface for Linux users that want to run it off their Dropbox account, but it turns out doing 150,000+ iterations of pkcs5-pbkdf2 is really expensive in JavaScript, and I really really miss the hotkey popup you get on the Mac.

So I wrote a Linux version.

This just reads your existing 1Password keychain and lets you hit the hotkey combo the Mac version expects (alt-meta-\, at least on my keyboard), to get your encrypted keychain at your fingertips at any time. Much faster to find the password you want and get it on the clipboard.

Lots of work to do still. It's a janky thing I wrote quickly, but it's already really useful to me personally, so have a peek if you like it.

Enjoy! Merry Christmas!﻿
Eric O'Brien's profile photoRyan Gordon's profile photoPaulo A Ferreira's profile photoJ. Pablo Pérez Trabucco's profile photo
+Eric O'Brien "./1pass & exit" is what I do. Leaves it running, kills the shell immediately.﻿
Add a comment...
So I've got two kinds of logins on various websites: those with incredibly shitty passwords, and those with passwords I can't remember. Okay, three: those that force you to change it all the damned time, which results in incredibly shitty passwords that I can't remember.

I decided enough is enough, so I installed 1Password, which is pretty good. Now I've got a pile of massive random strings for passwords everywhere. I don't even know them and don't have to. I paid through the damned nose, but it's nice on Mac OS X and iOS, and if you're syncing it to Dropbox, the thing does some javascript magic so you can open the key file in your web browser on Linux to get a UI, which is pretty cool.

But here's what I learned:

- Some websites make it really hard to change your password. More than one had me Googling for "[website name] change password" to figure out how to do it. That's pretty fucked up. Steam makes you use their desktop client to do it, and you can't change it through the website at all, as far as I could tell, which is also fucked up.

- Many websites would complain if you failed all sorts of stupid requirements. Must have at least one number, must not have more than 9 numbers, must have at least one capital letter, must have at least one non-alphanumeric character, must not have any repeating characters, etc. Must have 8 to 16 characters, which brings me to my next point...

- If a site says you can't have more than X characters, they're probably storing your original password. I imagine that site's database has a "varchar(16)" field for your password. If they are hashing them--like they damned well should--they will always end up being the same size in their database and they shouldn't care if you entered five or fifty characters...which brings me to the next point...

- More than one site, if you gave it a 50-character password, or a password with an uncommon (but low-ASCII) character, would report that your password was successfully changed, but then fail to log in with that password. I had to get a password reset emailed to me and pick a smaller (or saner) password. Buffer overflow? String handling fail? Don't know.

Thankfully 1Password had sliders for tweaking the random string it generates, to cooperate.

And finally:
- It's an interesting exercise to think of all the places you have an account. I bet you've forgotten lots of them. Trying to go back and add a crazy random password to every thing I could think of took a lot longer than I expected, and I'm sure I've only started.﻿
Mark Felder's profile photoLeon Nardella's profile photoJake Magee's profile photoFred Richards's profile photo
 ·  Translate
Add a comment...

Ryan Gordon

Shared publicly  - 
"9. Hacker News. In fact, all of the overeager startup hangers-on and fedora-wearing 'bitch, make me a sandwich' tools convinced code will save the world, whose willful blindness just helps perpetuate a sexist, racist, classist environment where white guys with computer science degrees can continue jerking off other white guys with computer science degrees until millions of dollars fall in their laps and they can shout, 'MERITOCRACY.'"

Paul Cutler's profile photoMike Melanson's profile photoDiego Elio Pettenò's profile photomeg ford's profile photo
+Diego Elio Pettenò Just kidding. I've got nothing against fedoras (the hat or the Linux distro). Try not to pay too much attention to people like the article's author. Especially on the internet, it's not hard to find people who are determined to hate you personally for any of a variety of reasons. Learn not to let it bother you.﻿
Add a comment...
Have him in circles
1,633 people
    Ninja, present
Charlotte, NC
Philadelphia, PA - Tustin, CA - Raleigh, NC
Stick it in the camel and go.
  • Queens University
Basic Information