Valve Backs SDL 2.0 to Strip Porting Friction Across PC and Mobile

Game Development with SDL 2.0 (Steam Dev Days 2014) — Steamworks Development

Steamworks Development

Adopting a permissive zlib license and hardware-agnostic shims enables commercial developers to deploy a single C codebase across desktop and mobile platforms without licensing liabilities or performance loss.

AI-assisted summary of Game Development with SDL 2.0 (Steam Dev Days 2014) — original source. Check the original for full context.

Source published:

Key ideas

  • SDL 2.0 completely overhauled SDL 1.2 and relicensed from the LGPL to the permissive zlib license, allowing commercial closed-source titles to statically link the library without legal complications on platforms like iOS. (5:19)
  • Valve relies on SDL across all shipped Linux and macOS titles and directly integrates its subsystems into the Steam client and Big Picture Mode to normalize controller mappings. (2:23)
  • SDL 2.0 avoids build-time library coupling by dynamically discovering APIs via dlopen and LoadLibrary, enabling seamless fallbacks like moving from Wayland to X11 on Linux. (10:11)
  • The framework's Game Controller API standardizes disparate third-party gamepad hardware into an Xbox 360 controller layout using GUID-based mapping strings crowdsourced through Steam Big Picture Mode. (31:19)

Detailed notes

## Background Published on YouTube by Steamworks Development on February 11, 2014, this presentation from Steam Dev Days 2014 features independent game porter Ryan Gordon (Icculus). According to the video description, the talk provides a high-level overview of Simple DirectMedia Layer 2.0, exploring its core features and illustrating how it helps developers build, port, improve, and maintain multiplatform titles.

## TL;DR Ryan Gordon presents the architecture of Simple DirectMedia Layer 2.0, highlighting its transition to the permissive zlib license, pure C foreign-function design, and hardware abstraction across desktop, mobile, and embedded platforms. He contrasts SDL's streamlined two-call window setup against verbose native frameworks like Direct3D 9, showcasing its hardware-accelerated 2D render pipeline, touch inputs, and native OpenGL context management. The talk details key subsystems including low-level PCM audio streaming, synchronization primitives, and the crowdsourced Game Controller API that maps fragmented gamepads into a standardized Xbox 360 layout. Illustrated by real-world ports like Dungeons of Dredmor, the overview concludes with utility tools, C runtime independence, and upcoming roadmap additions such as Wayland support and dynamic binary overrides.

## Atmosphere & style The presentation is breezy, practical, and infused with Ryan Gordon's trademark irreverent wit, making low-level systems programming feel lively and accessible. Speaking without a single line of code on his slides, Gordon balances seasoned developer pragmatism with dry punchlines about porting to toaster ovens, wrestling with legacy APIs, and dodging scary licenses. The room carries the relaxed, collegial camaraderie of an engineering conference, giving listeners the experience of hearing unvarnished war stories from a veteran who genuinely enjoys solving platform plumbing.

## Bulletin - [05:19](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=319s) SDL 2.0 completely overhauled SDL 1.2 and relicensed from the LGPL to the permissive zlib license, allowing commercial closed-source titles to statically link the library without legal complications on platforms like iOS. - [02:23](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=143s) Valve relies on SDL across all shipped Linux and macOS titles and directly integrates its subsystems into the Steam client and Big Picture Mode to normalize controller mappings. - [10:11](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=611s) SDL 2.0 avoids build-time library coupling by dynamically discovering APIs via dlopen and LoadLibrary, enabling seamless fallbacks like moving from Wayland to X11 on Linux. - [31:19](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=1879s) The framework's Game Controller API standardizes disparate third-party gamepad hardware into an Xbox 360 controller layout using GUID-based mapping strings crowdsourced through Steam Big Picture Mode.

## Key takeaways - [05:19](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=319s) SDL is implemented in pure C to ensure zero-friction bindings with scripting environments like Python, Lua, and native C++ engines. - [08:39](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=519s) The rewrite from SDL 1.2 to 2.0 modernized the codebase to be 64-bit clean and endian-clean, expanding hardware abstractions from 8 to 16 distinct subsystems. - [14:16](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=856s) SDL's modular subsystem opt-in design ensures uninitialized subsystems, such as audio, never query devices or interfere with external middleware like FMOD or Miles Sound System. - [15:10](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=910s) Unlike SDL 1.2's single-window constraint, SDL 2.0 supports multi-window and multi-monitor setups, mapping displays and virtual desktop coordinates natively. - [16:55](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=1015s) The performance overhead of SDL is negligible because platform dispatch is routed through direct function pointers rather than complex runtime conditional checks. - [19:18](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=1158s) The hardware-accelerated 2D render API provides GPU texture batching and scaling, enabling legacy software-rendered titles to support modern display scalings and the Steam Overlay. - [23:03](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=1383s) Full OpenGL and Direct3D pipelines can be initiated directly after window creation, granting titles access to modern rendering pipelines without engine restrictions. - [26:34](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=1594s) The Steam Controller is treated distinctly from conventional gamepads in SDL because it presents to the operating system as a mouse and keyboard, requiring Steamworks API integration. - [29:53](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=1793s) SDL provides a dual-layer controller architecture, pairing raw axis and button enumeration with a standardized Xbox 360 controller abstraction layer. - [34:16](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=2056s) Valve actively aggregates and filters user gamepad configurations through Steam Big Picture Mode to crowdsource production-ready controller mappings directly into SDL. - [35:53](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=2153s) The Haptic API provides a unified cross-platform interface supporting low-level waveform synthesis as well as a high-level, fire-and-forget dual-motor rumble model. - [38:56](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=2336s) SDL audio operates as a low-level PCM streaming callback that automatically manages channel downmixing, surround conversion, and sample format resampling on dedicated threads. - [41:15](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=2475s) Threading primitives wrap native operating system implementations and propagate thread names directly into debuggers like Visual Studio and GDB. - [42:51](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=2571s) On Windows platforms, SDL bypasses fragmented MSVCRT runtime dependencies by implementing internal standard library utilities and using Win32 heap calls directly. - [46:07](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=2767s) The abstract SDL_RWops stream interface enables unified, seamless read and write operations across disk files, raw memory blocks, and network sockets. - [48:06](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=2886s) The Dynamic API architecture ensures that even statically linked SDL binaries can be overridden or patched at runtime by users or Steam client updates without recompilation.

## Detailed walkthrough ### [00:01](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=1s) Introduction and Speaker Background

Ryan Gordon (often known online as "icculus") takes the stage at Steam Dev Days to discuss Simple DirectMedia Layer 2.0 (SDL 2.0). Setting his presentation clock so he doesn't talk too fast, he invites the audience to raise hands and jump in whenever they have questions, noting that the lighting in the room is good enough to actually see everyone. He emphasizes that if attendees ask interesting questions, he is completely open to abandoning the slides and following the conversation wherever it leads. The session is intentionally high-level, focused on how SDL can make a game developer's life better, rather than walking through lines of code: “I don't think there's a single line of code in this entire slide deck so don't panic about that.”

Gordon outlines his background as an independent contractor who has been porting games to Linux, macOS, and virtually anything else for 15 years: “My name's Ryan, I port stuff to Linux and Mac OS and, you know, the toaster oven in your apartment.” He shows a slide with logos resembling a NASCAR jacket to demonstrate the sheer breadth of studios and titles he has worked on. Pointing to a picture of his young daughter, Olive, he quips that she is currently his biggest client. When an audience member asks if he is "the guy that Humble uses to port everything," Gordon confirms that he is one of them, pointing out that fellow Humble porters are also sitting directly in the room with him.

- **Speaker**: Ryan Gordon (Icculus), freelance game porter and developer for 15 years. - **Audience engagement**: Encouraged questions throughout; slides published at libsdl.org after the presentation. - **Focus**: High-level functionality and architecture rather than syntactic code walkthroughs.

---

[02:23](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=143s) What is SDL and Where Did It Come From?

Gordon introduces Simple DirectMedia Layer—abbreviated as SDL, treating "DirectMedia" as a single component—as the open-source community's answer to Microsoft DirectX. On Windows, developers historically reached for DirectX when building a game from scratch to handle video and audio interfaces. However, outside Windows, platforms like macOS and Linux lacked DirectX entirely. SDL stepped into that gap: while it uses a different syntax and library structure than DirectX, it exposes access to the exact same hardware capabilities in an easier, faster-to-develop manner.

```mermaid flowchart TD accTitle: Origin and Evolution of SDL accDescr: Diagram tracing the development of SDL from Executor through Loki Software to Valve and modern games.

subgraph Origins["Early History"] A["Sam Lantinga creates SDL<br/>for Executor (Mac OS Classic emulator)"] B["Loki Software hires Lantinga<br/>SDL becomes standard Linux porting layer"] end

subgraph Modern["Modern Adoption"] C["SDL 1.2 legacy era<br/>(Dreamcast, PalmOS, Amiga)"] D["SDL 2.0 redesign<br/>(Modern desktop & mobile)"] E["Valve Games & Steam Client<br/>Millions of players worldwide"] end

A --> B B --> C C --> D D --> E ```

SDL began roughly 15 years prior when Sam Lantinga (who was present in the audience) created it to build Executor, an early emulator for classic Mac OS. Lantinga was subsequently hired by Loki Software, an early commercial Linux porting house. Loki adopted SDL as its core foundational framework, dedicating an entire engineering staff to enhancing, stress-testing, and standardizing it for high-end games. Over a decade and a half of sustained development, it grew into the de facto standard for Linux game development. By 2014, all of Valve's shipped Linux/Mac games relied on SDL, the Steam client itself integrated SDL for various subsystems, and millions of gamers ran SDL code daily.

- **Origins**: Created by Sam Lantinga for the Mac OS emulator *Executor*, then matured at Loki Software. - **Track record**: Over 15 years of continuous open-source development, maintenance, and bug fixing. - **Modern role**: Shipped in every Linux/Mac Valve release and built into parts of the Steam client. - **Version 2.0**: Shipped in late 2013 / early 2014, representing a complete modernization; Gordon mentions they will not discuss legacy SDL 1.2 "except to make fun of it."

---

[05:19](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=319s) Core Philosophy: C Architecture, zlib Licensing, and Portability

Explaining why SDL is designed the way it is, Gordon points out that it deliberately handles the repetitive, ugly boilerplate that developers usually copy-paste between projects: “It makes hard things easy, that's the simple part of Simple DirectMedia Layer.” The library is intentionally authored in plain C rather than C++. Aside from historical reasons—C compilers were historically more reliable across obscure targets—pure C enables trivial foreign-function bindings for high-level scripting languages. Consequently, environments like Python (via Pygame/PySDL2) and Lua feature first-class SDL bindings.

A major strategic pivot in SDL 2.0 was relicensing. While SDL 1.2 used the GNU LGPL (Lesser General Public License), the development team stripped out old legacy code and relicensed SDL 2.0 entirely under the permissive zlib license:

> “We removed all the code from that, we changed the license, we made sure we had permission to do this, because we found that the LGPL is really, really scary for developers and even if you could use it with closed-source stuff, it was questionable and people got nervous about it.”

Gordon illustrates this by contrasting the zlib license—which fits cleanly on a single slide or postcard—with the LGPL, which would have required 22 slides at the same font size. Under the zlib license, developers can freely download, modify, and statically link SDL into commercial, closed-source games without legal complications; the only rules are essentially that developers cannot claim they wrote the original code, should not remove the license attribution, and cannot sue the authors if the software breaks.

```mermaid flowchart LR accTitle: SDL Supported Platform Matrix accDescr: Overview of desktop, mobile, and embedded platforms officially supported by SDL 2.0.

subgraph Desktop["Desktop OS"] W["Windows"] M["macOS"] L["Linux"] U["Unix (FreeBSD / Solaris)"] end

subgraph MobileEmbedded["Mobile & Embedded"] A["Android"] I["iOS"] R["Raspberry Pi (OpenGL ES)"] H["Haiku (BeOS successor)"] end

SDL2["SDL 2.0 Core"] --> Desktop SDL2 --> MobileEmbedded ```

While SDL 1.2 famously targeted obscure platforms like Amiga, Dreamcast, and Palm OS, SDL 2.0 refocused its maintenance footprint on modern, relevant systems:

- **Desktop**: Linux (Gordon's primary development environment), Windows, macOS, and general Unix variants (FreeBSD, Solaris). - **Mobile**: Android and iOS, reflecting the reality that mobile is an inescapable chunk of the game market. - **Embedded & Alternative**: Raspberry Pi (providing direct OpenGL ES context creation on the $35 microcomputer) and Haiku (the open-source continuation of BeOS), proving the framework retains deep low-level portability.

[08:39](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=519s) The Expanding Scope of SDL 2.0 Subsystems

Ryan Gordon ("Icculus") highlights that Simple DirectMedia Layer 2.0 is 64-bit clean and endian-clean, making ports to new hardware architectures straightforward. To illustrate how much the library has matured, Gordon recalls that the subsystem overview slide for SDL 1.2 had only eight bullet points; for SDL 2.0, that list has grown to sixteen. These subsystems cover everything required to construct a cross-platform game foundation: video management (creating windows, managing windows, and putting bits onto the screen), audio delivery (streaming raw PCM data directly to audio cards), and an input event queue (mouse clicks, keyboard strokes, and joystick motion).

```mermaid flowchart TD accTitle: SDL 2.0 Core Subsystems Architecture accDescr: High-level overview of the functional areas managed by SDL 2.0.

subgraph VideoInput["Display & Input"] V["Windowing & Display Management"] R["2D Hardware-Accelerated Renderer"] E["Event Queue System"] J["Joystick & Game Controller APIs"] H["Haptics (Force Feedback)"] end

subgraph AudioSys["Audio Pipeline"] A["Low-level PCM Audio Streaming"] end

subgraph OSAbstraction["OS & Hardware Utilities"] T["Threading & Synchronization"] D["Dynamic Library Loading (dlopen / LoadLibrary)"] C["CPU Feature Detection (SSE, etc.)"] P["Power & Battery Monitoring"] end ```

Beyond core display and sound, SDL 2.0 bundles a simple 2D rendering API for lightweight games, low-level joystick support, a higher-level game controller abstraction that spares developers from juggling quirky hardware mappings, and haptic support for force feedback. It also eliminates the need to maintain platform-specific boilerplate code scattered throughout a codebase. Utility wrappers handle dynamic library loading across OS boundaries, detect CPU instruction capabilities like SSE4.2, manage multi-threading primitives, and query whether a laptop is running on battery power. An audience member asks what developers should do regarding modern consoles like Xbox 360, Xbox One, PlayStation 3, and PlayStation 4; Gordon clarifies that while the team is actively thinking about console support, they do not have a concrete plan rolled out yet.

- **Clean codebase:** Full 64-bit cleanliness and endian neutrality ensure broad platform compatibility. - **Scope expansion:** SDL 1.2 provided 8 subsystems, whereas SDL 2.0 provides 16. - **Hardware utilities:** Built-in APIs detect CPU features (such as SSE4.2), query power/battery status, manage threads, and load shared libraries without platform-specific `#ifdef` directives.

[10:11](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=611s) Multiple Dynamic API Targets Without Static Linkage

Addressing what he means by "multiple API targets," Gordon explains the volatility of OS-level driver interfaces over time. On Linux, for instance, display rendering historically meant talking to an X server, but newer display servers like Wayland and Mir are replacing it. A game programmed strictly against the X11 API might fail to run in future environments. Similarly, sound architecture on Linux has cycled through several iterations over the past decade. If an application locks itself into a specific library, the binary ages poorly.

SDL solves this longevity problem by decoupling itself from concrete platform libraries at build time. Rather than linking against `libX11` or ALSA, SDL inspects the running host dynamically via `dlopen` (or `LoadLibrary` on Windows). It evaluates available system technologies and selects the optimal path at runtime without bothering the end user:

> “There is nothing that SDL links against except the standard C runtime, and on Windows we don't even link against that.”

If an environment offers Wayland, SDL attempts to load it; if Wayland support is missing, it transparently falls back to X11, leaving the user unaware that any fallback occurred. This shifting landscape is by no means unique to Linux. Windows developers have had to navigate waveOut, DirectSound, XAudio2, and WASAPI, with the possibility of another API change in future OS releases. SDL insulates games from that churn by absorbing the platform variations underneath an unchanging interface.

[12:05](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=725s) Direct3D Boilerplate vs. SDL Simplicity

Demonstrating the core philosophy of keeping the library simple, Gordon contrasts the boilerplate of native graphics APIs with SDL's design. Addressing the room of Windows programmers at Steam Dev Days, he walks through the official Microsoft documentation's recommended approach to open a Direct3D window from scratch without a helper framework. The walk-through requires four dense slides of shrinking code: defining and registering a window class, querying video adapter hardware capabilities, selecting frame buffer pixel formats, verifying refresh rates, and determining whether 3D acceleration is supported before a window ever appears.

``` Microsoft Direct3D 9 SDK Sample (4 Slides) ┌─────────────────────────────────────────────────────────┐ │ WNDCLASSEX wc = { sizeof(WNDCLASSEX),... }; │ │ RegisterClassEx(&wc); │ │ D3DPRESENT_PARAMETERS d3dpp; │ │ ZeroMemory(&d3dpp, sizeof(d3dpp)); │ │ IDirect3D9* pD3D = Direct3DCreate9(D3D_SDK_VERSION); │ │ D3DCAPS9 caps; │ │ pD3D->GetDeviceCaps(D3DADAPTER_DEFAULT,...); │ │ CreateWindowEx(0, "ClassName", "Title",...); │ │ pD3D->CreateDevice(..., &pd3dDevice); │ │ /* (Still missing complete error handling checks...) */ │ └─────────────────────────────────────────────────────────┘ vs. SDL 2.0 Initialization ┌─────────────────────────────────────────────────────────┐ │ SDL_Init(SDL_INIT_VIDEO); │ │ SDL_Window *win = SDL_CreateWindow("hello", │ │ SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, │ │ 640, 480, SDL_WINDOW_SHOWN); │ └─────────────────────────────────────────────────────────┘ ```

Gordon jokes that while the example looks pathological, it is Microsoft's canonical implementation, adding dryly that “they make themselves look bad because if you could actually read this on this slide, there is no error checking in that example.” Accounting for actual failure states makes the Direct3D setup even longer. By comparison, Gordon displays the entire equivalent code using SDL 2.0:

```c SDL_Init(SDL_INIT_VIDEO); SDL_Window *win = SDL_CreateWindow("hello", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, SDL_WINDOW_SHOWN); ```

Those two calls produce a ready-to-use 640×480 window titled "hello," fully prepped to accept 3D drawing commands. Toggling a single flag switches the window between desktop fullscreen and a windowed presentation. When an audience member playfully points out that Gordon omitted error handling in his SDL snippet as well, Gordon quips that viewers can add the two missing `if` statements as an exercise. He emphasizes that streamlining unglamorous setup chores makes software engineering substantially more pleasant:

> “So a lot of things that you've looked at and said, ‘Uh, give it to the intern,’ this is much easier and much more satisfying as a programmer to work with over time.”

- **Native Direct3D overhead:** Direct3D window creation spans multiple registration stages, capability queries, and format verifications spanning pages of boilerplate. - **SDL window initialization:** Accomplished via `SDL_Init` and `SDL_CreateWindow`, setting size, positioning, fullscreen flags, and system registration in two lines.

[14:16](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=856s) Modular Initialization and Subsystem Selection

Subsystems in SDL 2.0 operate on an opt-in model controlled by bit flags passed to `SDL_Init()`. Developers assemble only the systems they require (such as `SDL_INIT_VIDEO | SDL_INIT_AUDIO`), leaving unused functionality completely inert:

> “You pick the subsystems you want and you ignore the subsystems you want.”

This modular design prevents the engine from invading software stacks that already use specialized external solutions. If a project relies on third-party sound runtimes like FMOD, OpenAL, or the Miles Sound System, omitting the `SDL_INIT_AUDIO` flag ensures SDL never queries, touches, or interferes with the host audio device. Gordon points out that while certain couplings exist—mouse and input events fundamentally necessitate the video subsystem to establish an OS window—developers retain fine-grained control over library dependencies. While static linking makes it possible to strip unreferenced subsystems out of the compiled binary entirely, Gordon recommends dynamic linking for general deployment so user-side driver bug fixes remain drop-in replacements.

[15:10](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=910s) Modern Display Capabilities and Context Management

The SDL 2.0 video layer was completely overhauled to support multi-monitor desktop environments. Unlike SDL 1.2, which restricted applications to a single global window to cater to 1990s game architectures, SDL 2.0 treats multiple windows and multiple displays as first-class citizens. Applications can enumerate active monitors, calculate their relative positions across virtual desktop space, inspect supported refresh rates and display modes, and direct windows to specific targets.

```mermaid flowchart LR accTitle: SDL 2.0 Display and Context Binding accDescr: Pipeline showing how SDL manages multi-monitor enumeration and binding to graphics contexts.

subgraph HardwareDisplays["Display Infrastructure"] D1["Display 1 (1080p Primary)"] D2["Display 2 (4K Secondary)"] end

subgraph SDLVideo["SDL 2.0 Video Subsystem"] W1["SDL_Window A"] W2["SDL_Window B"] end

subgraph GraphicsTargets["Rendering API Binding"] G1["OpenGL / GLX / WGL Context"] G2["Direct3D Device"] G3["OpenGL ES / EGL Context"] G4["SDL Software Surface"] end

D1 --> W1 D2 --> W2 W1 --> G1 W1 --> G2 W2 --> G3 W2 --> G4 ```

On top of multi-display placement, SDL acts as an agnostic canvas for rendering backends. Developers can draw using standard software surfaces, OpenGL, OpenGL ES, or Direct3D. Gordon stresses that managing an OpenGL context via WGL on Windows or GLX on Linux is historically just as painful as configuring Direct3D. SDL abstracts that complexity into a couple of attribute setters (such as color depth and buffer properties) followed by a single context generation call. In response to an audience question asking whether SDL automatically handles lost graphics contexts in OpenGL and Direct3D, Gordon notes that when using Direct3D, SDL yields direct access to the underlying Direct3D device so developers can test device loss directly; for OpenGL, context-loss recovery features are currently being explored in the development pipeline for future releases.

- **Multi-display enumeration:** SDL 2.0 maps out connected displays, virtual desktop coordinates, and available resolutions for multi-monitor setups. - **Multiple windowing:** Replaces the single-window limitation of SDL 1.2, permitting multi-window utilities, debugging views, and tools. - **Graphics API abstraction:** Generates and binds rendering contexts for OpenGL, OpenGL ES, Direct3D, or pure software rendering behind a consistent interface.

[16:55](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=1015s) SDL Overhead, Video API Foundations, and Native Message Boxes

An audience member asks about the performance overhead of using SDL. Ryan Gordon explains that the overhead amounts to just a function call or two, as SDL is engineered to stay out of the developer's way as a very thin shim that dispatches immediately to underlying platform calls. Rather than evaluating massive chains of `if` statements at runtime to determine whether the environment is Wayland, X11, or a Raspberry Pi, the library uses internal function pointers that jump directly into the correct native backend. Gordon emphasizes that this wrapper overhead will not even register in a profiler. The only cost that typically shows up is system-level operations like buffer swaps in OpenGL, which exist regardless of whether a game uses SDL or raw native code:

> “The answer is a function call or two—we mostly stay out of your way and it's mostly a very thin shim that figures out what the platform wants and goes directly to those platform calls.”

Turning back to the video subsystem, Gordon notes that the API exposes standard windowing and GUI events, including mouse hovering and focus loss, cleanly abstracting away the messy event pumping typical of Win32 message loops. He highlights SDL's built-in message box API, acknowledging that having an explicit function for modal alerts might sound trivial on paper. However, implementing a proper graphical error dialog across various operating systems and display servers without crashing or hanging the host process is notoriously tricky:

> “Message boxes, which seems really silly to be like ‘we support message boxes,’ but those are actually really hard to do on some platforms, you would be incredibly surprised. So we actually have an API that will figure out how to get just an error dialog on the screen if you need one, so... sounds ridiculous, one function call that will save your life.”

[18:12](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=1092s) Surfaces, Textures, and Low-Level Video Abstractions

Gordon breaks down the fundamental concepts underpinning the SDL 2.0 video architecture:

* **Windows (`SDL_Window`):** Standard OS windows with title bars that can be configured as resizable, borderless, or fullscreen. * **Surfaces (`SDL_Surface`):** 2D pixel buffers stored strictly in system RAM. While SDL 1.2 frequently attempted to push surfaces into video memory via DirectDraw, SDL 2.0 formalizes surfaces as CPU-side memory. * **Textures (`SDL_Texture`):** Hardware-accelerated pixel buffers that live directly inside GPU VRAM, allowing even simple 2D games to push graphics workloads to modern display hardware.

```mermaid flowchart TD accTitle: SDL 2.0 Graphics Rendering Paths accDescr: Diagram comparing the SDL 2D Renderer pipeline with the direct 3D API pipelines.

subgraph CPU["System Memory"] A["SDL_Surface<br>(CPU Pixel Buffer)"] end

subgraph GPU["Video Memory (VRAM)"] B["SDL_Texture<br>(GPU Texture)"] C["OpenGL Context<br>(Core / ES / Extensions)"] D["Direct3D Device / Native Handle"] end

subgraph Output["Display Target"] E["SDL_Window<br>(Screen Output)"] end

A -->|"Upload"| B B -->|"SDL_RenderCopy"| E C -->|"SDL_GL_SwapWindow"| E D -->|"Native Render & Swap"| E ```

For 3D graphics, SDL provides deep, battle-tested support for cross-platform OpenGL. However, developers who prefer Direct3D are fully accommodated: SDL can instantiate a Direct3D rendering device object directly, or simply hand over the native window handle (`HWND` on Windows) so developers can plug in custom rendering pipelines, avoiding the platform boilerplate demonstrated earlier in the talk.

[19:18](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=1158s) The 2D Render API and Modernizing Legacy Titles

SDL 2.0 introduces a dedicated hardware-accelerated 2D rendering API. Gordon whimsically frames its design target:

> “You should think of this as the most hyped up Super Nintendo you've ever seen.”

The render API does not try to replace full-scale OpenGL, but it provides a clean, immediate set of GPU-backed drawing operations. Developers can load textures into GPU memory and treat them like high-speed sprites, perform hardware alpha blending, draw basic primitives like lines and rectangles, and execute rotations, scaling, and color modulation. It serves as an ideal framework for rapid prototyping, casual 2D titles, or updating vintage software-rendered games from the 1990s.

Gordon points out that many classic titles—such as *Duke Nukem 3D* or early DirectDraw projects—struggle on modern machines because they blit directly to CPU framebuffers. By porting their blitting logic to SDL 2.0 textures, studios gain hardware scaling that eliminates tiny "postage stamp" presentation on high-resolution monitors, along with automatic compatibility with modern graphics features like the Steam Overlay.

[20:58](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=1258s) Case Study: Porting *Dungeons of Dredmor* Across Platforms

To showcase the power of the 2D Render API, Gordon shares an experiment conducted on *Dungeons of Dredmor*, a popular 2D roguelike developed by Gaslamp Games (whose co-founder, Nicholas Vining, is sitting in the audience). The game originally rendered by writing directly into a CPU-bound framebuffer. When ported to SDL 2.0:

1. **Steam Overlay Fix:** The software blits were converted to GPU textures. Because the Steam Overlay requires either an active OpenGL or Direct3D context to hook into, this transition immediately enabled the overlay on Windows, solving a long-standing user complaint. 2. **iOS Porting with Zero Code Changes:** Moving the game to an iPad required zero lines of game logic modification. Furthermore, SDL automatically translated iOS touchscreen tap events into standard mouse clicks, allowing the existing mouse-driven UI to work seamlessly without custom touch-gesture code. 3. **Raspberry Pi Deployment:** The exact same codebase was compiled and executed on a Raspberry Pi connected to an HDTV, again with zero game code modifications.

Gordon jokes that while the game is running on a Raspberry Pi sitting atop an old console, “we didn't get it working on that Dreamcast at the bottom yet, but what can you do.” He also issues a clear disclaimer on behalf of Gaslamp Games:

> “Gaslamp Games asked me to tell you that they are not actually shipping this, you know—maybe they'll experiment with it, but we just did this for fun to see if we could do it. Don't start knocking on their door for the Raspberry Pi port.”

[23:03](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=1383s) Direct OpenGL Context Management and Events

For games demanding full 3D capabilities, Gordon presents the standard SDL OpenGL context lifecycle. Setting up a cross-platform context requires only creating an `SDL_Window` with the `SDL_WINDOW_OPENGL` flag, invoking `SDL_GL_CreateContext` on that window, issuing standard OpenGL drawing commands, and calling `SDL_GL_SwapWindow` to display the frame. Gordon jokingly admits to omitting error checking in his slides, calling himself “a hypocrite all the way to the end.”

When Gordon suggests this trivializes OpenGL usage, SDL co-creator Sam Lantinga interjects from the audience to emphasize that this abstraction conceals immense rendering power. Gordon agrees, explaining that between the context creation call and the window buffer swap, developers can implement state-of-the-art engines:

> “As Sam pointed out, I just minimized that anything you can do with OpenGL, you can do where that comment is. You can get to incredibly complex stuff—you can write Crysis 12 right there, you can write Unreal Engine 14, you can do anything. All of OpenGL is available to you here at this point.”

He notes that this exact sequence powers the rendering backends for major commercial titles like *Team Fortress 2*, *Painkiller: Hell & Damnation*, and *Serious Sam 3*. SDL also simplifies modern feature discovery: checking whether an OpenGL extension is supported requires a single function call with an extension name string, allowing developers to query for features like newer shader profiles dynamically.

Gordon concludes the segment by introducing SDL's event subsystem. SDL consolidates keyboard strokes, mouse clicks, motion, and window events (such as resizing or loss of focus) into a normalized, unified event queue processed via a standard polling loop (`SDL_PollEvent`). Developers simply inspect the returned event structure for specific types—such as `SDL_MOUSEMOTION`, `SDL_KEYDOWN`, or `SDL_QUIT`—giving games complete control over windowing inputs with minimal code.

[25:27](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=1527s) Cross-Platform Event Loop and Touch Input

Ryan Gordon explains the universality of the SDL 2.0 event loop. While platforms like Windows and macOS natively require completely different event structures—such as Cocoa event processing on Apple systems versus traditional Win32 message pumps—SDL abstracts these variations entirely so that game code remains unchanged across platforms. Beyond typical keyboard, mouse, and window-resizing notifications, the API natively surfaces touch events for touchscreen environments like iOS and Android. By default, SDL maps touch interactions to mouse events to ensure backwards compatibility with standard pointer logic, but it flags the event with metadata signaling that the input actually originated from a finger. This design allows developers who care about touch differentiation to filter out simulated mouse clicks, while existing desktop code paths continue working without modification.

For more sophisticated input handling, SDL 2.0 can track multiple simultaneous touch points and includes an integrated gesture recognition engine termed "$1 gestures" (Dollar Gestures). This allows games to record custom touch gestures, prompting SDL to fire an event when a player inputs that specific gesture or swipe pattern.

```mermaid flowchart TD accTitle: SDL 2.0 Touch and Event Pipeline accDescr: Diagram showing how OS inputs are abstracted into unified SDL events or simulated mouse clicks.

subgraph NativeOS ["Operating System Layer"] WinMsg["Windows Message Pump"] CocoaMsg["macOS Cocoa Loop"] TouchDev["iOS / Android Touchscreen"] end

subgraph SDLCore ["SDL 2.0 Input Layer"] EventPump["Unified Event Loop"] TouchProc["Touch & Dollar Gestures Engine"] end

subgraph GameApp ["Game Application"] GameEvents["SDL_Event Handler"] MouseFallback["Standard Mouse Logic (Finger-tagged)"] end

WinMsg --> EventPump CocoaMsg --> EventPump TouchDev --> TouchProc TouchProc -->|"Raw Touch & Multi-finger"| EventPump TouchProc -.->|"Touch-as-Mouse"| MouseFallback EventPump --> GameEvents ```

- SDL normalizes window resizing, touch, mouse, and custom application events into a uniform polling structure. - Dollar Gestures enable developers to record custom multi-point swipe gestures and receive high-level callback events. - Touch events masquerade as mouse events by default to preserve legacy mouse-driven code paths without breaking existing interfaces.

---

[26:34](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=1594s) Controllers, Platform Support, and the Steam Controller

Shifting focus toward physical controllers, Gordon outlines the dual-layered nature of SDL’s controller stack, which scales from raw axis-and-button notifications up to a high-level abstraction modeled on the Xbox 360 layout. An attendee asks whether this includes native support for the Steam Controller. Gordon clarifies that it does not: to the operating system, the Steam Controller reports as a mouse and keyboard rather than a traditional joystick, meaning developers must interface with it through the Steamworks API rather than SDL's gamepad subsystem.

Another audience member inquires whether gamepads on iOS and Android are supported through SDL. Gordon states that Android gamepad support had just landed, whereas iOS support had historically been held back because Apple only recently introduced an official game controller framework with iOS 7. While early third-party peripherals like the Atari Arcade controller were not implemented, Gordon notes that native iOS 7 joystick integration was slated for the next minor SDL release:

> “We do not have that yet but it's easy to add and it doesn't take any changes to your code once we add it.”

- Timers in SDL allow games to trigger periodic custom events on a defined millisecond interval without spinning up ad-hoc thread workers. - The Steam Controller operates outside SDL’s joystick system, requiring direct integration via the Steamworks API. - Android gamepad support is active in SDL 2.0, with iOS 7 controller framework support scheduled for the subsequent update.

---

[28:08](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=1688s) The Realities of Porting: Baldur's Gate and the zlib License

A developer in the audience who worked on the port of *Baldur's Gate: Enhanced Edition* mentions that a year prior, their team utilized SDL 2 for iOS touch inputs, but ended up bypassing SDL to query iOS directly for advanced gestures like pinch-to-zoom. Gordon praises *Baldur's Gate* and acknowledges that SDL's touch gesture engine has continued to mature, but uses the anecdote to emphasize a broader philosophical truth about cross-platform game development: achieving portability does not exempt a developer from providing native platform polish.

He highlights that moving SDL from the LGPL to the permissive zlib license was specifically motivated by closed platforms like iOS, where static linking rules and App Store restrictions made LGPL compliance legally fraught. Yet even when code compiles cleanly across targets, games still require tailored platform adjustments:

> “Everyone hates it when a Windows game has a little logo from like a PlayStation controller so like you know you you are going to have to consciously clean up those things in your game and your particular issue is something we might be able to handle better but that's worth noting that we make you portable but you still need to give it your own polish and make it a good program to run in the first place.”

- *Baldur's Gate: Enhanced Edition* relied on SDL 2 on iOS for core input, while falling back to native iOS frameworks for complex multi-touch gestures. - The transition from LGPL to the zlib license removed friction around static linking on mobile platforms with strict sandboxing like iOS. - Portable code must still be paired with platform-specific UX considerations, such as proper touch interactions or matching controller button glyphs.

---

[29:53](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=1793s) Low-Level Joysticks vs. DirectInput Woes

Turning to the architecture of joystick handling, Gordon explains that SDL handles as many simultaneous sticks as the underlying OS can detect. The API is hotplug-aware: if a player rage-quits and unplugs their gamepad, SDL delivers a disconnect notification, and when a friend plugs in an extra controller, the game receives an event allowing it to seamlessly announce a new challenger. Developers can consume joystick input either by polling the hardware state for immediate data dumps (similar to XInput) or by capturing discrete button and axis change notifications directly from the event queue.

However, Gordon points out that relying strictly on low-level device enumeration—querying raw axes, buttons, POV hats, and vendor strings—echoes the long-standing nightmares of Microsoft's DirectInput. Historically, developers were burdened with building extensive in-game calibration screens because every third-party flight stick and pad reported axes and button indexes differently:

> “Now that's the lowlevel API and anyone's ever dealt with direct input knows that this is kind of a hard API to use because there are a million joysticks out there and they all look different they all work a little differently and it's a little frustrating.”

- Supports dynamic device insertion and removal events at runtime without restarting the game or input subsystem. - Developers can choose between state polling and an event-driven queue for processing button and axis changes. - Raw joystick enumeration returns axis counts, button counts, hat switches, and descriptive hardware strings like "Logitech WingMan 3D".

---

[31:19](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=1879s) The Game Controller API and Crowdsourced Hardware Mappings

Gordon contrasts the historical mess of DirectInput with Microsoft’s XInput, noting that while XInput was vendor-restrictive by only supporting official Xbox 360 controllers, it provided a predictable, standardized layout that game developers loved. To solve this dilemma without arbitrary hardware lock-in, SDL 2.0 introduced the Game Controller API. This abstraction establishes a universal virtual layout modeled on an Xbox 360 controller—featuring four face buttons, twin clickable analog thumbsticks, analog triggers, shoulder bumpers, a directional pad, and standard Home/Start/Back buttons.

```mermaid flowchart LR accTitle: SDL 2.0 Game Controller Normalization accDescr: Hardware GUIDs and community databases map heterogeneous gamepads to an Xbox 360 layout.

subgraph RawDevices ["Heterogeneous Hardware"] PS3["DualShock 3"] Generic["No-Name USB Pad"] Retro["SNES via USB Adapter"] end

subgraph SDLMapping ["SDL 2.0 Mapping Engine"] GUID["Read USB Vendor/Product ID (GUID)"] DB["Mapping Database (Steam Big Picture)"] end

subgraph StandardizedLayout ["Game Controller API"] VirtualX360["Standardized Xbox 360 Form Factor (A, B, X, Y, Triggers, Bumpers, Sticks)"] end

PS3 --> GUID Generic --> GUID Retro --> GUID GUID --> DB DB --> VirtualX360 ```

To normalize the sea of bizarre third-party controllers manufactured across the globe, SDL parses each peripheral’s OS-level GUID (derived from its USB vendor and product IDs). It then references an internal database to map those proprietary button and axis indices directly into standardized Xbox button roles. An attendee asks if retro hardware adapters—like an original Super Nintendo pad connected via USB—can function within this system; Gordon confirms they can, provided a mapping profile exists for that adapter. Because manually cataloging thousands of obscure controllers is impossible for a small developer team, Gordon reveals that Valve crowdsources mapping definitions through Steam's Big Picture controller configuration tool.

> “Everyone wants an Xbox controller because they wrote to XInput and they built their whole game around that input model so we gave you that but we've done we take it a bit further what we've done is we've started collecting gamepads and controllers and all the weird things you can buy in like the street corner in New York City that was made somewhere in China by the lowest bidder and has no actual discernable name but fortunately it has a valid USB vendor ID and product ID so we look at these we look at the GUID that is presented to the operating system we say we know what to do with that controller.”

- The Game Controller API maps arbitrary hardware to an Xbox 360 schema: A/B/X/Y, Start/Back/Guide, dual clickable sticks, D-pad, bumpers, and analog triggers. - Peripherals are matched using USB Vendor ID and Product ID combinations exposed through the operating system GUID. - Popular controllers like the DualShock 3 work out of the box with built-in profiles. - Unidentified devices and USB console adapters can be mapped into SDL's database via Steam Big Picture's configuration interface.

[34:16](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=2056s) Crowdsourced Game Controller Database and Edge Cases

Continuing with the Game Controller API, Ryan Gordon details how controller configurations are collected and unified across Steam. Whenever a player customizes their controller inside Steam Big Picture Mode, that mapping is captured and reported back to Valve. Valve aggregates the submissions until a threshold is reached to weed out joke submissions or corrupted mappings. Once confirmed as common, the profile becomes a default entry in the database. When a user connects that specific gamepad, Steam identifies the device, configures it, and passes the configuration string directly down to SDL upon launching the game.

```mermaid flowchart TD accTitle: SDL 2.0 Game Controller Configuration Pipeline accDescr: Diagram illustrating how Big Picture Mode captures mappings, sends them to Valve to aggregate, and propagates them to games via SDL.

subgraph Collection["Mapping Aggregation"] A["User configures gamepad in Big Picture Mode"] --> B["Configuration sent to Valve servers"] B --> C{"Sufficient consistent mappings?"} C -- "Yes (Not a troll)" --> D["Added to default SDL controller database"] C -- "No" --> B end

subgraph Runtime["Game Launch & Execution"] D --> E["User plugs in controller"] E --> F["Steam identifies device & passes mapping string to SDL"] F --> G["SDL normalizes input to standardized Xbox layout"] end ```

For unsupported peripherals, developers and players can manually supply bindings using a dedicated configuration utility, an environment variable, or a flat configuration file. These bindings consist of simple mapping strings equating raw hardware inputs to standardized logical buttons (e.g., matching button index 1 to the standard `X` button). This system allows bizarre or legacy gamepads to function out of the box while sidestepping the rigid hardware constraints of Windows XInput. On Windows, SDL can still utilize XInput underneath the hood for official Xbox 360 controllers, but exposes an identical abstract interface across all operating systems.

Gordon takes questions from the floor regarding edge cases, specifically controllers that have fewer or more buttons than a standard Xbox 360 controller. He emphasizes that while the API is less flexible than raw DirectInput, it serves the vast majority of standard arcade and action titles.

> “If you're writing a flight simulator you absolutely do not want to use this, but if you're writing you know Super Mario Brothers or hell, even Pilotwings, you know, this is what you should be using.” — Ryan Gordon

- **Crowdsourcing Validation:** Valve verifies that mappings are submitted repeatedly across different users before promoting them to production defaults to prevent troll submissions. - **Handling Missing Buttons:** If a physical gamepad lacks certain inputs (such as analog triggers), SDL simply never fires events for those inputs; Gordon jokes, “We can't physically make buttons appear out of nowhere.” - **Excess Buttons:** Controllers with extra buttons must have those surplus inputs mapped onto the standard Xbox layout or accessed via the lower-level raw Joystick API.

[35:53](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=2153s) The Haptic Force Feedback API

Gordon moves on to the Haptic API, joking about the linguistic origins of the term: “Haptic is either Latin or Greek, I can't remember what, for force feedback.” The API supports gamepads as well as specialized vibrating mice (such as older force-feedback models from Logitech). It provides two levels of control: an advanced direct-control mode modeled after DirectInput, and a simple, high-level interface. Under the direct model, games can query device capabilities for specific periodic waveforms—including sine, square, or triangle waves—and execute fine-tuned waveforms directly.

For common game development needs, developers can avoid low-level synthesis by using simple directional rumble. The API exposes independent controls for the left (heavy/low-frequency) and right (light/high-frequency) motors, matching the standard Xbox 360 controller architecture. It also features a non-blocking “fire-and-forget” rumble model:

> “There's a fire and forget model: you say just vibrate this thing for... 3,000 milliseconds, and then just stop and don't even let me know—I don't really want to track this and manage it, just make the thing rumble for a little bit and get back to me and just keep going.” — Ryan Gordon

Gordon notes personal satisfaction with this API. For many years while porting commercial games to Linux, force feedback had no standard implementation, forcing him to stub out all vibration code. With SDL 2.0, force feedback works cross-platform across Mac, Linux, and Windows without platform-specific code paths.

[38:56](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=2336s) Low-Level Audio Architecture: A Relentless Stream of PCM

The SDL 2.0 Audio API is built intentionally at an extremely low level, conceptually mirroring the direct memory access (DMA) buffers of DirectSound. Gordon prefaces this topic by warning attendees that the native SDL audio layer may be too low-level for direct use in game logic, and is meant instead for engine developers who have already implemented spatialization, mixing, and sound asset decoders.

> “Really it's incredibly low level; it's what I call a relentless stream of PCM.” — Ryan Gordon

The system functions via an audio callback that SDL invokes whenever the hardware buffer requires more samples. This callback executes on a dedicated audio thread managed by SDL—a significant architectural evolution from the Mac OS Classic days, when SDL 1.2 had to run its audio callback inside a raw hardware interrupt. The engine provides uncompressed raw PCM data in memory, and SDL converts and resamples it on the fly to match whatever the platform's backend requires.

| Channel Layouts Supported | Sample Formats Supported | Platform Backend Examples | |:--- |:--- |:--- | | Mono | 8-bit unsigned | Mac OS X: Core Audio (prefers native float) | | Stereo | 16-bit signed (little/big-endian) | Windows Modern: WASAPI / DirectSound | | Quadraphonic | 32-bit floating point (little/big-endian) | Windows Legacy: WaveOut (prefers integer) | | 5.1 Surround | Integers (various signed/unsigned bit depths) | Linux: ALSA / PulseAudio | | 7.1 Surround (in active development) | | |

Because the engine must handle spatial attenuation, panning, decoding, and multichannel mixing manually when using this API directly, Gordon recommends that developers evaluate existing higher-level middleware if they do not want to write audio pipelines from scratch: - **SDL_mixer:** A satellite library built on top of SDL that wraps audio formats like MP3/OGG, handles music and sound-effect channels, and automates basic stereo panning. - **OpenAL:** A cross-platform 3D audio API providing hardware-accelerated spatialization. - **Commercial Audio Middleware:** Fully featured third-party engines such as FMOD or the Miles Sound System.

[41:15](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=2475s) Threading Primitives and Platform Abstraction

Gordon introduces SDL’s threading primitives, anchored by `SDL_CreateThread`. Beyond abstracting `CreateThread` on Windows and `pthread_create` on POSIX systems, SDL incorporates debugger integration: developers pass a string naming the thread, and SDL executes platform-specific routines to inject that label directly into native debuggers like Visual Studio or GDB. This makes identifying rogue threads painless when managing dozens of background tasks.

In addition to traditional synchronization primitives—mutexes, semaphores, and condition variables—SDL 2.0 provides cross-platform atomic operations. Gordon stresses the danger of implementing atomic memory operations manually:

> “Everyone's written compare-and-swap code and been scary; we offer those for you, we figure out how that works on your platform if the system offers it.” — Ryan Gordon

If the underlying operating system provides atomic intrinsics, SDL routes calls through them. If not, SDL injects compiler- and architecture-specific machine opcodes (such as x86 or ARM assembly instructions) behind an identical C call, such as comparing and swapping 32-bit integers or pointers. Gordon then briefly introduces shared library management, pointing out that cross-platform codebases are perpetually littered with messy `#ifdef` blocks balancing Windows `LoadLibrary` against POSIX `dlopen`, which SDL cleanly unifies behind a single cross-platform dynamic loader interface.

[42:51](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=2571s) System Utilities, Standard Library Replacements, and Memory Management

Ryan Gordon outlines SDL 2.0's collection of auxiliary platform utilities designed to spare developers from platform-specific boilerplate. Dynamic library loading is unified: you request to open a library, look up a symbol, and get back either a pointer or null. Because platforms like X11 lack a simple native pop-up dialog comparable to Windows, SDL constructs an actual window styled like an OS message box when no native system implementation exists, ensuring developers always have an easy way to present fatal errors: “sometimes you just need to be like everything's broken I'm about to report this game I'm sorry um and that's what a message box is for”. Clipboard access is abstracted for getting and setting data, and a fallback interface called `SysWM` provides access to raw, native window handles (such as Win32 window handles) under `#ifdef` blocks whenever deep OS-level calls are inescapable. Additional utilities query CPU features (SSE, MMX, or legacy PowerPC AltiVec) and processor speeds.

To bypass C runtime fragmentation, SDL replaces critical standard C runtime routines with safe, uniform implementations. Historically, Microsoft Visual Studio lacked `snprintf`, leaving developers with the dangerous buffer-overflow-prone `sprintf`, while Linux provided robust `snprintf` support. On Windows, SDL avoids linking against the MSVC C runtime entirely by implementing its own routines, including memory allocation via direct Win32 API calls, eliminating runtime DLL mismatch issues. When an audience member asks if developers can redirect SDL's internal allocations to a custom system allocator callback, Gordon clarifies that `SDL_malloc` does not currently support allocator hooks:

```mermaid flowchart TD accTitle: SDL Cross-Platform Utilities and Memory Flow accDescr: Diagram illustrating SDL 2.0 utility layers and memory handling between game code and operating systems.

subgraph AppLayer["Game Application"] GameCode["Game Logic"] end

subgraph SDLCrossPlatform["SDL 2.0 Abstraction Layer"] DynLib["Dynamic Library Loading<br/>(Open / Symbol Lookup)"] MsgBox["Message Boxes<br/>(Native or Emulated)"] SysWM["SDL_SysWM<br/>(Raw Native Window Handle)"] StdLib["C Runtime Wrappers<br/>(snprintf, string ops)"] SDLMem["SDL_malloc<br/>(Internal Allocator)"] end

subgraph OSBackends["Operating System APIs"] Win32API["Windows Win32 API<br/>(Direct Heap Calls, No MSVCRT)"] X11Wayland["Linux / X11 / Wayland"] AppleOS["macOS / iOS Cocoa"] end

GameCode --> DynLib GameCode --> MsgBox GameCode --> SysWM GameCode --> StdLib GameCode --> SDLMem

DynLib --> OSBackends MsgBox --> Win32API MsgBox --> X11Wayland SysWM --> Win32API SDLMem -->|"Direct Heap Allocation"| Win32API ```

- Message boxes automatically fall back to custom rendered windows on platforms without built-in dialog dialogs. - `SDL_SysWM` exposes platform-specific window handles for emergency low-level operations. - The standard library wrappers supply consistent string operations and memory functions across compilers. - An allocator callback interface is not present in 2.0, but Gordon notes it as a strong candidate for SDL 2.1: “not the best answer maybe we'll put that in 2.1 it's actually not a bad idea um because we we should do that honestly”.

[46:07](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=2767s) Timers, File I/O Abstractions, Power State, and `SDL_main`

Gordon reviews high-resolution timing, noting that SDL provides `SDL_GetTicks` for millisecond tracking and wraps high-performance hardware counters akin to Windows' `QueryPerformanceCounter`. For data streaming and storage, `SDL_RWops` provides an abstract stream interface built on function pointers, allowing audio decoding (such as loading WAV files) and file access to pull uniformly from disk, system memory buffers, or network streams. Standardized filesystem queries resolve install paths and user save directories, preventing games from dumping save files haphazardly into installation directories across Windows, OS X, and Linux.

The power management subsystem checks battery status, remaining charge percentages, and AC power connectivity, which is vital for mobile platforms and laptops while gracefully reporting no battery on desktop towers. Gordon also praises SDL's assertion framework over the standard `<assert.h>`, referencing community write-ups highlighting its depth: “The Angels Sing and weep when we code this thing”. Finally, the optional `SDL_main` static runtime code wraps Windows' `WinMain` requirement, letting developers write a single standard `int main(int argc, char *argv[])` across every target platform without touching core entry points.

- `SDL_RWops` uses function pointer tables to read data identically from files, memory buffers, or live sockets. - File system path APIs determine correct platform-compliant directories for save games and read-only assets. - Battery queries detect power state, percentage, and remaining run time. - `SDL_main` translates platform-specific initialization code like `WinMain` to classic C `main()`.

[48:06](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=2886s) The Near Future Roadmap: Upcoming SDL Features and Enhancements

Turning to near-term developments, Gordon outlines features nearing release across the repository. SDL's input subsystem is preparing multi-mouse support so separate local players can each control an independent cursor on the same desktop. Audio capture (microphone recording) and video capture (webcam input) are entering the API surface, alongside 7.1 surround sound output topologies. On Linux, Wayland support is already committed to the Mercurial repository, Mir support is progressing, and Gordon mentions an experimental side project utilizing `libdrc` to stream game frames directly to a Nintendo Wii U GamePad for novel wireless play.

On the ecosystem front, a Windows RT port and full compatibility with the Windows Store are staged for upstream integration to allow SDL titles to clear Windows certification. For legacy projects, an upcoming compatibility wrapper called `sdl12-compat` will allow binaries linked against the classic SDL 1.2 dynamic library to execute on top of the SDL 2.0 engine without recompiling source code. Furthermore, a dynamic API mechanism will enable games to statically link SDL while still allowing end users and Steam to override the runtime dynamically with hotfixes. Gordon closes the feature list by inviting developer requests: “crazy ideas are sometimes really good ideas so don't be afraid”.

- Multi-mouse support enables distinct hardware tracking for multiple desktop users. - Multimedia expansion adds audio capture, webcam recording, and native 7.1 surround output. - Wayland support is landed in Mercurial source control; Mir backend work is in progress. - Windows Store compatibility facilitates certification for Windows RT and UWP ecosystems. - `sdl12-compat` allows legacy SDL 1.2 applications to harness the SDL 2 backend without requiring a recompile. - The Dynamic API allows static linking safety with dynamic override capability.

[50:06](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=3006s) Community Infrastructure, Quality Assurance, and Conclusion

Gordon highlights the project's development and testing infrastructure. Community interactions are maintained through bi-directionally synchronized mailing lists and web forums, comprehensive wiki documentation, and a Bugzilla database where the team has resolved more than 2,000 bug tickets. Stability across disparate targets is verified by continuous integration: “we have a build bot we build this thing on like 14 different platforms for every single commit we do to sdl uh so that if it breaks on a platform we know immediately and it nags us very loudly”.

Because scheduled talk time has expired due to taking audience questions throughout the presentation, Gordon invites attendees to meet him directly offstage for further discussion. He displays his contact details, slides links, Twitter, and Google+, finishing with a quip regarding social platforms: “if you're still using Facebook man it's time to reevaluate your life thank you very much”.

## Notable quotes > [05:19](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=319s) It makes hard things easy, that's the simple part of Simple DirectMedia Layer. — Ryan Gordon

## Mentioned ALSA, Android, Baldur's Gate: Enhanced Edition, Bugzilla, Core Audio, Direct3D, DirectDraw, DirectInput, DirectSound, DirectX, DualShock 3, Duke Nukem 3D, Dungeons of Dredmor, Executor, FMOD, Gaslamp Games, GDB, Haiku, Humble Bundle, iOS, libdrc, Loki Software, Mercurial, Miles Sound System, Mir, Nicholas Vining, Nintendo Wii U, OpenAL, OpenGL, OpenGL ES, Painkiller: Hell & Damnation, PulseAudio, Raspberry Pi, Ryan Gordon, Sam Lantinga, SDL 1.2, SDL 2.0, SDL_mixer, Serious Sam 3, Simple DirectMedia Layer, Steam, Steam Big Picture, Steam Controller, Steamworks API, Team Fortress 2, Valve, Visual Studio, WASAPI, WaveOut, Wayland, Windows RT, Windows Store, X11, Xbox 360, XInput

## Video description This talk will offer a high-level overview of Simple Directmedia Layer 2.0. It will cover the features of the library and how it can make your game easier to build, port, improve and maintain.

Speaker: Ryan Gordon (Icculus) Slides (PDF): http://media.steampowered.com/apps/steamdevdays/slides/sdl2.pdf Slides (PowerPoint): http://media.steampowered.com/apps/steamdevdays/slides/sdl2.ppt

[Source](https://www.youtube.com/watch?v=MeMPCSqQ-34)

中文简报

Valve力挺SDL 2.0,消除PC与移动端移植阻碍 采用宽松的zlib许可证并引入硬件无关垫片层,使商业开发者能够将单一C代码库部署到桌面和移动平台,免除许可法律风险或性能损耗。 Ryan Gordon介绍了Simple DirectMedia Layer 2.0的架构,重点强调其向宽松zlib许可证的转变、纯C外部函数设计,以及跨桌面、移动和嵌入式平台的硬件抽象。他将SDL仅需两次调用即可完成的窗口配置与Direct3D 9等冗长的原生框架进行了对比,展示了其硬件加速2D渲染管线、触控输入和原生OpenGL上下文管理能力。演讲详细阐述了核心子系统,包括底层PCM音频流、同步原语,以及通过众包将碎片化手柄映射为标准化Xbox 360布局的Game Controller API。通过《英雄地下城》(Dungeons of Dredmor)等实际移植案例,概述最后介绍了实用工具、C运行库独立性,以及Wayland支持和动态二进制覆盖等未来路线图规划。 SDL 2.0彻底重构了SDL 1.2,并将许可证从LGPL更改为宽松的zlib许可,允许商业闭源游戏在iOS等平台上静态链接该库而无需担心法律纠纷。 (5:19) Valve在所有已发布的Linux和macOS游戏中均依赖SDL,并将其子系统直接集成到Steam客户端和“大屏幕模式”中,以规范化控制器映射。 (2:23) SDL 2.0通过dlopen和LoadLibrary在运行时动态发现API,避免了构建时的库耦合,从而实现了无缝回退机制,例如在Linux上从Wayland回退到X11。 (10:11) 该框架的Game Controller API通过Steam大屏幕模式众包获得的基于GUID的映射字符串,将分散的第三方手柄硬件标准化为Xbox 360控制器布局。 (31:19)

Reading summary

At Steam Dev Days 2014, Ryan Gordon argued that Simple DirectMedia Layer 2.0 (SDL 2.0) serves as an essential, high-performance cross-platform foundation that insulates game developers from operating-system churn and boilerplate. Re-architected in C under the permissive zlib license, the framework standardizes graphics, audio, input, and platform utilities across modern desktop, mobile, and embedded hardware. C Architecture, Relicensing, and Dynamic Decoupling (5:19) Originating with Sam Lantinga for classic Mac OS emulation and matured through commercial Linux porting at Loki Software, SDL 2.0 shifted strategically from the legacy GNU LGPL to the zlib license. Gordon noted that LGPL compliance caused legal friction for developers targeting closed, sandboxed platforms like iOS. Relicensing permitted unencumbered static linking in proprietary commercial games. Authored in pure C, the library facilitates direct foreign-function bindings for high-level scripting languages such as Python and Lua, while running across desktop platforms, mobile operating systems like iOS and Android, and embedded devices like the Raspberry Pi. Abstracting Dynamic APIs Without Overhead (10:11) To prevent precompiled game binaries from degrading as platform drivers evolve, SDL avoids static linkage against concrete system libraries such as ALSA or libX11. Instead, it queries the runtime environment via dynamic loaders (such as dlopen or LoadLibrary) and uses internal function pointers to bind directly to modern backends like Wayland or fall back seamlessly to legacy X11. Gordon explained that on Windows, SDL does not even link against the MSVC C runtime, instead wrapping critical string operations and allocating memory through direct Win32 calls. He noted this layer functions as a thin shim introducing negligible overhead—roughly a function call or two—leaving standard operations like OpenGL buffer swaps to dominate execution time. Streamlined Windowing and Modern Graphics Pipelines (12:05) Contrasting native graphics APIs with SDL, Gordon demonstrated that opening a Direct3D window from scratch requires multiple slides of capability checks and format negotiations, whereas SDL reduces initialization to calling SDL_Init and SDL_CreateWindow. Unlike SDL 1.2, which was restricted to a single window, version 2.0 natively manages multi-monitor enumeration, coordinate mapping, and context binding for Direct3D, OpenGL, and OpenGL ES. It also formalizes CPU-bound pixel buffers as SDL_Surface while introducing SDL_Texture and a hardware-accelerated 2D Render API to manipulate GPU-side sprites. In a case study on Gaslamp Games' Dungeons of Dredmor, moving software blits to SDL textures resolved Steam Overlay rendering issues on Windows and allowed the game to execute on iPad and Raspberry Pi without modifying gameplay logic. Unified Input and Crowdsourced Gamepad Mappings (25:27) SDL 2.0 unifies disparate platform event loops—including Win32 pumps and Cocoa event handlers—into a singular polling queue. Touch events masquerade as mouse events by default to maintain desktop compatibility, but include metadata and support custom Dollar Gestures. To eliminate the historical calibration issues of DirectInput without being locked into Microsoft's vendor-restricted XInput, SDL introduced the Game Controller API. This subsystem uses hardware GUIDs to map arbitrary gamepads into a standard Xbox 360 layout. Valve crowdsources these profiles by collecting controller configurations from Steam Big Picture users, promoting consistent community mappings to production defaults once verified against trolling. Low-Level Audio, Multithreading, and System Abstractions (38:56) The SDL audio subsystem functions intentionally at a low level, feeding an ongoing stream of PCM samples via an audio callback running on an independent thread, with automatic on-the-fly sample rate conversion. For higher-level mixing and decoding, Gordon recommended middleware like SDL_mixer, OpenAL, or FMOD. Beyond media, SDL exposes cross-platform threading with debugger label injection, cross-platform atomic operations, high-resolution timers, battery monitoring, and the SDL_RWops abstraction for reading from files, memory, or network sockets interchangeably. It also standardizes filesystem queries for save data and provides dynamic dialog fallbacks when operating systems lack native message boxes. Gordon emphasized that while SDL handles cross-platform plumbing, developers remain responsible for tailoring user experiences to each target platform, such as adapting interface layouts or multi-touch gestures. Near-term roadmap goals for the project at the time included multi-mouse input, audio and webcam capture, native 7.1 surround output, Wayland integration, and an sdl12-compat wrapper to run legacy binaries seamlessly on the modern SDL 2.0 architecture.

精炼阅读摘要

资深跨平台移植开发者 Ryan Gordon(Icculus)在 Steam Dev Days 2014 演讲中指出,SDL 2.0 经由全面重构、采用宽松的 zlib 许可并扩展至 16 个核心子系统,消除了繁杂的平台样板代码与底层驱动变动风险,已成为现代跨平台游戏开发的标准化底层基础设施。 架构演进与宽松许可转向 (2:23) SDL(Simple DirectMedia Layer)由 Sam Lantinga 最初为 Mac OS 模拟器 Executor 编写,经 Loki Software 历练,演变为 Linux 及跨平台游戏的事实标准,广泛运行于 Valve 旗下游戏与 Steam 客户端。Gordon 指出,SDL 2.0 彻底摆脱了旧版 1.2 的历史包袱,不仅实现了 64 位整洁度与字节序中立,还从限制严格的 GNU LGPL 重新授权为极为宽松的 zlib 许可证。LGPL 条款长达数十页且对静态链接和闭源分发存在法律顾虑,而 zlib 许可证仅一张明信片大小,允许商业闭源游戏在 iOS 等受限平台上直接静态链接,开发者仅需保留版权署名且不得声称拥有原始源码。同时,SDL 坚持使用纯 C 语言编写,不仅跨平台编译器支持度最高,也便于 Python 和 Lua 等脚本环境实现无缝的外部函数接口(FFI)绑定。 动态加载设计与极简视窗管理 (10:11) 针对各操作系统显示与音频接口频繁更迭的痛点,SDL 2.0 采用了 build 时与具体驱动库解耦的设计。Gordon 强调,SDL 并不在构建时硬编码链接 libX11 或 ALSA,而是通过 dlopen 或 Windows 的 LoadLibrary 在运行时探测环境;当系统支持现代显示协议 Wayland 时即优先调用,若缺失则无缝降级至 X11,Windows 端同样在 WASAPI、DirectSound 与 XAudio2 间动态适配,且在 Windows 上完全不链接 MSVC C 运行时库。在图形与视窗管理上,SDL 2.0 消除了微软 Direct3D 官方示例中长达数页、充斥适配器查询与像素格式比对的繁重样板代码,仅需 SDL_Init 与 SDL_CreateWindow 两行代码即可建立功能完备的窗口。该版本原生支持多显示器坐标枚举与多视窗实例,且底层封装仅消耗一到两个函数调用的微小开销,直接将调用路由至原生平台接口。 双轨图形路径与旧作现代化实践 (18:12) SDL 2.0 明确界定了三种显示抽象对象:宿主系统视窗(SDL_Window)、位于 CPU 内存的传统二维像素缓冲(SDL_Surface),以及驻留在 GPU 显存中的硬件加速纹理(SDL_Texture)。除为 OpenGL 提供由 SDL_GL_CreateContext 到 SDL_GL_SwapWindow 的跨平台上下文管理,并向 Direct3D 提供底层 HWND 句柄外,SDL 2.0 新设了一套轻量级 2D 硬件加速渲染 API。Gordon 将这套 API 戏称为超级任天堂的硬件加速版,它支持纹理旋转、缩放、透明混合与基础图元绘制,大幅简化了 2D 游戏开发。在以 Gaslamp Games 的《Dungeons of Dredmor》为案例的实验中,该作将原本直接写入 CPU 缓冲的软件渲染逻辑迁移至 SDL 2.0 纹理,在零业务逻辑修改的前提下,不仅解决了 Windows 端因缺乏三维上下文而无法唤出 Steam Overlay 的长期缺陷,还成功在 iPad 与树莓派上流畅运行,并将触控输入自动映射为鼠标点击。 手柄标准化与众包映射机制 (31:19) 面对传统 DirectInput 时代外设轴映射混乱、需在游戏中繁复校准的缺陷,以及 XInput 仅限于微软认证硬件的垄断性,SDL 2.0 推出了 Game Controller API。该接口建立了一个以 Xbox 360 手柄标准布局(双模拟摇杆、模拟扳机、肩键、方向键及标准动作键)为基准的虚拟控制模型。底层引擎抓取 USB 设备的厂商 ID(Vendor ID)与产品 ID(Product ID)生成唯一 GUID,再匹配数据库将硬件原始输入规范化。为覆盖市面上五花八门的第三方手柄及复古主机转接器,Valve 利用 Steam Big Picture 模式向全球玩家众包控制器映射,数据经多重一致性验证过滤恶作剧后,汇总推入 SDL 官方映射库;游戏启动时由 Steam 自动向 SDL 下发配置字符串。对于超出或缺失物理按键的特殊设备,SDL 采取未映射按键不派发事件的静默策略,并保留底层原始 Joystick API 供专业飞行模拟类游戏自由读取。 底层音频管线与全功能系统抽象 (38:56) SDL 2.0 的音频架构定位于“不间断的 PCM 裸流”,在底层利用独立音频线程周期性执行回调函数拉取数据,并在内存中动态执行重采样与格式转换,覆盖单声道至 5.1 环绕声以及 8 位整型到 32 位浮点等多种规格。Gordon 说明该低级音频接口并不内置空间化衰减与音频解码功能,建议非自研混音管线的团队搭配 SDL_mixer、OpenAL 或商业中间件使用。在操作系统辅助设施方面,SDL 2.0 提供了线程重命名并直接注入 Visual Studio 与 GDB 的调试支持、跨平台内存原子 CAS(比较并交换)操作、可统一读取磁盘/内存/网络的 SDL_RWops 抽象流、自动适配各平台规范的存档目录查询,以及电量状态监控与自制断言库。在缺乏原生对话框机制的环境下,SDL 甚至能自绘弹窗,确保致命错误能够明确呈现给用户。 SDL 2.0 通过 14 个平台的持续集成构建机、Mercurial 源码库管理以及超过 2,000 个 Bugzilla 问题的修复积累,维持了高度工程稳定性。尽管针对 Xbox One 与 PS4 等现代主机的支持在 2014 年初尚无具体落地规划,且 SDL_malloc 尚未集成自定义内存分配器回调,但即将上线的 Wayland/Mir 支持、Windows Store 认证兼容、多鼠标独立光标跟踪以及无需重编译即可运行旧程序的 sdl12-compat 兼容层,进一步巩固了其作为跨平台游戏核心基础设施的长期生命力。

Detailed notes — zh

## Background 本内容由 Steamworks Development 频道于 2014 年 2 月 11 日在 YouTube 平台上发布,记录了资深移植工程师 Ryan Gordon(Icculus)在 Steam Dev Days 2014 大会上的技术分享。视频简介指出,本场演讲对跨平台底层多媒体库 Simple DirectMedia Layer 2.0(SDL 2.0)进行了高层级综述,详细阐述其核心特性以及如何帮助开发者更轻松地构建、移植、优化与维护游戏工程。 ## TL;DR 演讲全面梳理了 SDL 2.0 相比 1.2 版本的现代化蜕变及其作为开源跨平台多媒体基础设施的核心价值。Ryan Gordon 详细介绍了 SDL 极简的窗口创建、极低开销的底层抽象、全新 GPU 加速的 2D Render API 以及对现代 OpenGL 上下文和多显示器的无缝支持。演讲重点解析了 SDL 革命性的游戏控制器(Game Controller)API 与 Steam 大屏幕模式的众包硬件映射机制,彻底解决了 PC 平台输入碎片化的历史痛点。最后,主讲人系统讲解了底层 PCM 音频流、原子并发多线程、动态库加载以及统一文件 I/O 等系统级封装,并展望了 Wayland 显示协议与老游戏平滑过渡层 sdl12-compat 等未来演进规划。 ## Atmosphere & style 现场氛围极其轻松欢快、妙趣横生,Ryan Gordon 以典型的极客幽默与脱口秀般的台风掌控全场,演讲中几乎没有枯燥的代码堆砌,取而代之的是密集的自嘲、即兴调侃与生动比喻。他与台下坐着的 SDL 创始人 Sam Lantinga 以及众多商业游戏开发者高频互动、有问必答,使得整场分享更像是一场顶级移植圈内极客的亲切聚会。台下笑声与掌声不断,观众能深刻感受到讲者对底层工程与跨平台自由度的极致热忱,既干货满满又充满感染力。 ## Bulletin - [05:18](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=318s) SDL 2.0 全面放弃严苛的 GNU LGPL 协议并转向宽松的 zlib 许可证,扫清了商业闭源游戏与 iOS 等移动端静态链接的法务合规障碍。 - [10:11](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=611s) SDL 采用零强依赖的运行时动态加载设计(如 dlopen/LoadLibrary),使游戏无需重新编译即可自适应底层图形与音频驱动的平滑升级与回退。 - [34:16](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=2056s) Valve 通过 Steam 大屏幕模式数百万玩家的手柄校准众包数据,为 SDL 游戏控制器 API 构建统一且免驱动配置的类 Xbox 360 映射数据库。 - [19:20](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=1160s) SDL 2.0 的 2D Render API 将老旧 CPU 软件渲染无缝转入 GPU 纹理管线,使经典 2D 游戏以零代码改动即可获得高分辨率缩放与 Steam 游戏内覆盖支持。 ## Key takeaways - [02:23](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=143s) SDL 被定义为开源世界对微软 DirectX 的直接替代,已成为 Linux 与 macOS 游戏事实上的行业底层标准,Valve 所有自研游戏及 Steam 客户端均深度依赖它。 - [05:18](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=318s) SDL 核心坚持由纯 C 语言编写,不仅规避了历史编译器 ABI 问题,更极大方便了向 Python、Lua 等脚本语言构建无缝 FFI 绑定。 - [16:55](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=1015s) SDL 2.0 是极薄的底层调用垫片(thin shim),内部通过函数指针直接分发,在性能分析器中 CPU 与函数调用开销几乎检测不到。 - [11:59](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=719s) 相比 Direct3D 需要数页复杂的窗口类注册与硬件检测样板代码,SDL 2.0 仅需一行 SDL_CreateWindow 即可拉起处于可用状态的 3D 渲染窗口。 - [11:59](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=719s) 模块化按需初始化设计允许开发者指定子系统,在引入 FMOD、Wwise 等第三方音频中间件时可完全避开对声卡硬件的抢占冲突。 - [15:10](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=910s) 视频子系统突破了 1.2 版本的单窗口瓶颈,完整支持多显示器枚举、独立坐标与分辨率管理,并简化了跨平台 OpenGL 上下文的创建与管理。 - [20:58](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=1258s) 2D Render API 借助显存纹理与硬件加速位图传输,让《地下城决战》等传统 2D 游戏以“零代码改动”直接跨平台运行至 iPad 与树莓派等设备。 - [25:27](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=1527s) 针对触摸交互提供了灵活兼容机制:多点触摸默认转译为鼠标事件以保障无缝兼容,同时也内置了 Dollar Gestures 手势识别及多指追踪支持。 - [29:55](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=1795s) 底层 Joystick API 虽支持完整热插拔与驱动轴探测,但面对输入碎片化难以维护;高层 Game Controller API 成功将其抽象为统一的类 Xbox 360 标准手柄模型。 - [35:53](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=2153s) Haptic 力反馈接口支持双马达独立振动并提供“即发即弃”的简易调用模型,由后台独立线程驱动振动,绝不阻塞游戏主渲染循环。 - [38:56](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=2336s) 音频子系统是一个底层的未压缩 PCM 数据泵,采用基于独立线程的回调机制向硬件灌入数据,并能自动在浮点与整型、多声道之间进行即时重采样。 - [41:16](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=2476s) 跨平台线程接口支持在底层注入线程显式名称,使其直接在各系统原生调试器中可见,极大降低了大规模并发项目的排错成本。 - [44:15](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=2655s) 在 Windows 平台下 SDL 完全不动态链接 C 运行时库(MSVCRT),连 malloc 都由底层自行实现,彻底规避了复杂的运行时版本依赖冲突。 - [46:07](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=2767s) SDL_RWops 抽象接口统一了文件、内存与网络数据流访问,配合标准的跨平台用户存储路径探测 API,彻底规范了各操作系统的权限与存档管理。 - [48:06](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=2886s) 开发规划包括 sdl12-compat 兼容垫片以无缝重定向老游戏、Dynamic API 热替换支持,以及针对 Wayland、Mir 与 Windows Store 的全面合规演进。 ## Detailed walkthrough ### [00:01](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=1s) 开场介绍与演讲基调 演讲由主持人开场,向听众引介来自 Icculus 的 Ryan Gordon,带来关于 Simple DirectMedia Layer 2.0(SDL 2.0)游戏开发的主题分享。Ryan 上台后先调侃着摆弄台上的计时时钟,生怕自己讲得太快,随后向台下听众明确了本场演讲的互动规则:听众可以随时举手打断提问,因为现场灯光并不刺眼,他能够清楚看到台下。他笑称,若有人提出了极具深意的好问题,他们甚至可能完全偏离原定幻灯片,展开一场全然不同的讨论。 关于演讲内容,Ryan 强调这是一次高层次的概览,主要目的是展示 SDL 能如何让开发者的工作和生活变得更轻松美好。整个幻灯片中甚至找不到一行具体的代码,因此听众不必紧张,重点在于理解 SDL 究竟能做什么,以便回去查阅文档并大展身手。所有幻灯片在演讲结束后都会立即上传至网络提供下载。他还留下了个人 Twitter 账号,打趣道大家可以在演讲期间发推文,若看到赞赏他会微笑,若是刻薄的批评他大概会哭出来,但无论哪种反馈都很有意思。 ### [01:20](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=80s) 讲者背景与业界经历 谈及个人身份与资历,Ryan 自我介绍为“为 Linux、Mac OS 甚至公寓里的烤面包机移植软件的人”。他作为一名全职自由职业者已经干了整整 15 年,未受雇于任何大公司,独立承接过大量知名 3A 巨作以及各类独立小游戏的跨平台移植工作。在不移植游戏时,他则专注于打造能让自己工作更高效的开发工具。他在幻灯片中展示了一张如同“赛车手赞助夹克(NASCAR jacket)”般的合作客户标志墙,上面密密麻麻布满了各类大型与小型游戏公司。接着他话锋一转,展示了自己目前最大的“大客户”——他的年幼女儿 Olive。 此时台下有观众发问,询问他是否就是那位负责为 Humble Bundle 移植几乎所有游戏的传奇人物。Ryan 幽默地承认自己确实是其中之一,并指着台下调侃道,另一位专门负责移植的大佬就坐在提问者的正前方,甚至还有其他同行也坐在附近,在场的移植工程师简直像个小型邪教聚会一样全员到齐。 ### [02:23](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=143s) 什么是 SDL:开源世界的 DirectX Ryan 正式切入主题,解释 Simple DirectMedia Layer 通常被简称为 SDL,可将“DirectMedia”视作一个合成词以理解这个三字母缩写。他将 SDL 形象地定义为开源世界对微软 DirectX 的回应。在传统的 Windows 游戏开发中,开发者会本能地使用 DirectX 提供的视频渲染、音频回放等子系统;但在 Windows 之外的 Mac 与 Linux 环境下,由于原生缺乏 DirectX,SDL 便成了开发者的首选替代方案。虽然 SDL 并没有沿用 DirectX 的 API 语法或函数集,但它能以更简单、更高效的方式让开发者获得近乎相同的底层硬件访问能力,并大幅压缩开发周期。 ```mermaid flowchart TD accTitle: SDL 与 DirectX 跨平台对比架构 accDescr: 对比 Windows 平台下 Direct3D/DirectSound 方案与基于 SDL 2.0 的跨平台游戏架构 subgraph WinPlatform["Windows 传统方案"] A["游戏代码"] --> B["DirectX (Direct3D / DirectSound)"] B --> C["Windows 硬件与系统"] end subgraph SDLPlatform["SDL 跨平台方案"] D["跨平台游戏代码"] --> E["SDL 2.0 统一抽象层"] E --> F["Windows"] E --> G["Linux / SteamOS"] E --> H["macOS / iOS / Android"] end ``` SDL 具备极强的跨平台特性与超过 15 年的代码积累。老版本 SDL 曾广泛移植至 Amiga、Sega Dreamcast、Palm Pilot 等极其古老的设备;而到了 SDL 2.0 时代,开发团队主动剔除陈旧代码,将重点收敛至现代平台。在业界应用上,SDL 承载了数以百万计的玩家群体:Valve 旗下的所有游戏(如《半条命》系列、《反恐精英》等)在对外发布时均深度集成了 SDL,甚至 Steam 客户端自身的某些核心功能也是基于 SDL 构建的。若玩家在 Mac 或 Linux 上运行过游戏,绝大多数情况下底层都在调用 SDL,即便在 Windows 平台上也有大量商业游戏采用它。 - 官方网站地址:`www.libsdl.org` - 经过 15 年的持续维护,积累了海量的漏洞修复与性能优化 - Valve 商业产品线(所有出货游戏及 Steam 客户端底层模块)全面采用 ### [04:10](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=250s) SDL 的历史沿革与 2.0 的诞生 回顾 SDL 的诞生历史,Ryan 介绍其最初由 Sam Lantinga 构思并发起(Sam 本人当时也坐在会场听众席中)。SDL 最初是为了运行一款名为 Executor 的经典 Mac OS 虚拟机兼模拟器而编写,其初衷是为该模拟器提供一种简单、优雅且跨平台的方式将画面位图(bits)推送到屏幕上。随后,知名移植厂商 Loki Software 聘用了 Sam。 Loki Software 专职将各类 PC 游戏移植到 Linux 平台,他们顺理成章地将 SDL 确立为公司移植技术栈的核心底层框架。Loki 投入了庞大的全职工程师团队,对 SDL 的各个子模块进行了深度拓展与工业级打磨。至此,SDL 逐步演变为 Linux 平台游戏开发的事实标准。Ryan 严肃地指出:“如果你想在 Linux 上编写游戏,这很可能就是你已经在使用的东西;如果还没有,那这就是你应该使用的东西。” 随着演讲前几个月的正式发布,项目迎来了全新的 SDL 2.0。Ryan 直言 2.0 是当前最具吸引力的新技术形态,带来了大量现代化特性。在整场演讲中,除非是为了调侃它落伍的设计,否则团队将完全不再讨论古老的 SDL 1.2。 ### [05:18](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=318s) 架构特性:从 C 语言设计到 zlib 许可证变革 Ryan 提炼了 SDL 2.0 的核心设计哲学与技术特性。它定位于现代操作系统生态,既覆盖桌面的 Windows、Mac OS、Linux,也延伸至移动端的 iOS 与 Android。SDL 践行“让复杂难题变简单”的原则——许多底层代码在不同引擎中经常被开发者机械地复制粘贴,它们编写繁琐、可读性极差但属于已解决的既有通用技术问题,SDL 的价值正是将这部分杂活彻底揽下。 在工程语言的选择上,SDL 完全由纯 C 语言编写。针对追求面向对象的 C++ 开发者,Ryan 宽慰大家“我们不戴有色眼镜看你”,但解释了纯 C 的关键工程考量:在项目发轫之初,主流 C 编译器的表现往往不尽如人意,而当时的 C++ 编译器则更为糟糕混乱;更重要的是,纯 C API 极大地降低了与脚本语言做互操作(FFI)的阻力。现今社区拥有极为活跃且高质量的 Python 绑定(Pygame / PySDL2),对于 Lua 及各类小众脚本语言,也都能轻松实现无缝绑定。 在开源许可证方面,SDL 2.0 做出了极为重要的决策:彻底弃用 GNU LGPL,全面拥抱宽松的 zlib 许可证。开发团队下大力气清理或重写了历史 LGPL 代码,确保获得完备的授权转换许可。Ryan 解释道,LGPL 在商业游戏开发者眼中是一头令人望而生畏的“怪兽”,即便是闭源集成也常引发法务上的困惑与疑虑。相比之下,zlib 许可证短小到足以印在一张明信片或一页 PPT 上。其核心内容极为简练自由: 1. 软件不提供任何担保,出现问题请勿起诉开发组; 2. 开发者在发布产品时若能提及使用了 SDL 会令人欣慰,但在法律层面绝不强制; 3. 不得篡改或抹除原始作者的版权署名。 开发团队允许所有人自由下载、魔改、静态链接或将其打包进闭源商业项目。 - 开发语言:纯 C 语言(便于 C++ 集成,原生利好 Python、Lua 等脚本语言绑定) - 许可证演进:从严苛且易引起闭源顾虑的 LGPL 转向极为宽松的 zlib License - 核心哲学:剥离样板代码(boilerplate),化简视窗、图形及多媒体底层复杂度 ### [07:47](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=467s) 跨平台支持矩阵与移动端战略 在谈及受支持平台时,Ryan 指出当前 SDL 2.0 的适配列表既包含了主流桌面生态,也涵盖了现代移动端与各类极客设备。Linux、Mac OS 和 Windows 构成了传统的“桌面三巨头”,也是开发与测试的核心战场。Ryan 自己绝大部分 SDL 核心开发均是在 Linux 环境下推进,而社区其他成员则分工保障 Windows 和 Mac OS 的平稳运行。对于 Unix 衍生版,Solaris 和 FreeBSD 等环境也依然保留着兼容通道。 与此同时,移动生态占据了极高优先级。由于智能手机的广泛普及,iOS 与 Android 已经成为不可忽视的游戏载体。正如 Ryan 所言:“Android 和 iOS 是必须支持的,因为无论我们喜欢与否,总有一天我们所有人都会在移动设备上玩游戏。”而在实验性与轻量级设备方面,SDL 2.0 兼顾了 BeOS 的现代继承者 Haiku,以此证明其架构卓越的可移植性;针对售价仅 35 美元的单板计算机 Raspberry Pi(树莓派),SDL 2.0 同样能够完美驱动并直接启用硬件级别的 OpenGL ES 加速支持。任何新平台的社区移植贡献,只要质量达标,官方团队都会积极合并吸收。 ### [08:39](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=519s) SDL 2.0 的子系统概览与主机支持现状 Ryan Gordon(Icculus)指出,SDL 2.0 具备 64 位纯净性(64-bit clean)和字节序纯净性(endian clean),因此移植到一个新平台相当轻松。在功能覆盖上,旧版的 SDL 1.2 幻灯片上只有 8 个要点,而 SDL 2.0 扩展到了 16 个子系统。这些子系统几乎涵盖了游戏底层的方方面面:视频子系统(处理窗口创建、窗口管理以及将像素传送到屏幕)、音频子系统(向声卡发送原始 PCM 数据)、事件处理(鼠标点击、摇杆触发等)、极简 2D 渲染 API、基础摇杆支持,以及更高层级的游戏手柄(Game Controller)API——开发者无需再为市面上千奇百怪的杂牌摇杆细节头疼。此外,它还提供了力反馈(Haptic/Force Feedback)支持,并封装了大量原本需要开发者手写平台特定宏分支的代码,例如动态链接库加载、处理器特性检测(如是否支持 SSE 4.2)、跨平台线程封装,以及笔记本电池状态检测等。 此时台下有观众打断提问,想知道针对 Xbox 360、Xbox One、PS3 和 PS4 等主机平台,开发者该如何处理。Gordon 解释称,目前 SDL 官方对这些主机平台还没有具体的支持方案,团队目前正在探讨如何解决该问题。 ### [10:11](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=611s) 动态加载与多 API 后端抽象机制 谈及多 API 目标支持(Multiple API Targets),Gordon 解释了这串词背后的实际机制与重要价值。以 Linux 系统为例,当前绝大多数用户依赖 X11(X Server)进行图形显示,但当时 Wayland 和 Mir 等全新显示服务器技术正在涌现,硬件交互方式随时可能生变。如果开发者在代码中硬编码直接绑定 X11,未来游戏在纯 Wayland 或 Mir 环境下可能根本无法启动。音频领域同样如此,老 Linux 用户深知音频 API 历经多次更迭(从 OSS 到 ALSA、PulseAudio 等)。 为了避免破坏兼容性,SDL 绝不会直接静态或动态链接到诸如 `libX11` 或 `libasound` 等具体库,而是通过运行时动态载入(在 Unix 上使用 `dlopen`,在 Windows 上使用 `LoadLibrary`)来搜寻系统现有的动态库。SDL 会自动探测当前系统可用的最佳硬件路径与技术栈;如果优先尝试 Wayland 失败,就会无缝回退到 X11。玩家完全感知不到底层切换,游戏依旧能正常开窗运行,开发者也无需在游戏代码里处理这些分支。 ```mermaid flowchart TD accTitle: SDL Runtime Dynamic Loading Flowchart accDescr: Shows how SDL detects and loads display and audio drivers at runtime using dlopen or LoadLibrary. subgraph AppLayer["游戏与调用层"] A["游戏主程序 (Game Logic)"] B["SDL 2.0 API 统一接口"] A --> B end subgraph DynamicCheck["运行时探测 (dlopen / LoadLibrary)"] C{"首选图形后端 (如 Wayland)"} D["回退图形后端 (如 X11)"] E{"系统音频驱动探测 (DirectSound / WASAPI / ALSA)"} B --> C B --> E C -->|"不可用"| D end subgraph DriverLayer["实际硬件交互驱动"] F["显示服务器 / 显卡驱动"] G["声卡驱动 (PCM 输出)"] C -->|"可用"| F D --> F E --> G end ``` 这种架构贯彻到了 SDL 的每一个子系统。在整个依赖链中,SDL 除了标准 C 运行时库(C runtime)之外不链接任何第三方系统组件;在 Windows 平台上,SDL 甚至做到了连标准 C 运行时都不链接。Gordon 强调,这种 API 变迁并非 Linux 独有,Windows 上的音频接口多年来同样从 WaveOut、DirectSound 演变到 XAudio2 和 WASAPI,因此抽象层的存在至关重要。 ### [11:59](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=719s) 简化开发的哲学:Direct3D 与 SDL2 的开窗对比 为了展现 Simple DirectMedia Layer 究竟有多“简单”,Gordon 现场对比了原生 Direct3D 与 SDL 2.0 的开窗代码。台下许多 Windows 开发者对此感同身受。在不依赖任何框架、纯原生调用 Direct3D 时,仅为了在屏幕上创建一个能用于 3D 渲染的窗口,就必须历经漫长繁复的样板代码:定义窗口类(Window Class)、向系统注册窗口类、查询显卡各项硬件属性、设置帧缓冲格式(Frame Buffer Format)、配置刷新率、检测硬件是否支持 3D 加速等。Gordon 一连翻了 4 张幻灯片,字体越来越小,甚至这 4 页官方推荐示例中还完全没有包含任何错误检查代码,实际生产中处理失败分支的代码量还要翻倍。 随后,Gordon 切换到 SDL 2.0 的等价实现——屏幕上仅用了一行核心调用: ```c SDL_CreateWindow("hello", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, SDL_WINDOW_SHOWN); ``` 一个带有 "hello" 标题栏、分辨率为 640x480 的窗口随即创建完毕,并立即处于可供 3D 绘图的状态。如果需要独占全屏,仅需传入一个标志位参数。当台下观众开玩笑指责 Gordon 自己的 SDL 代码示例同样“没有写错误检查”时,Gordon 调侃道:“作为留给观众的课后作业,你们可以在这里自行加上那两条 if 语句。”他总结道,游戏开发中许多让人想“推给实习生去写”的脏活累活,在 SDL 封装后都变得极其轻松: > “This is kind of how we built the whole API so a lot of things that you've looked at and said give it to the intern, this is much easier and much more satisfying as a programmer to work with over time.” —— Ryan Gordon - 模块化初始化设计:通过 `SDL_Init` 搭配按位或标志位(如 `SDL_INIT_VIDEO | SDL_INIT_AUDIO`)实现按需初始化; - 第三方库无冲突共存:如果项目已经集成了 FMOD、OpenAL 或 Miles Sound System,只需不传入音频标志位,SDL 就绝不会触碰声卡硬件,避免资源抢占; - 模块耦合约束:部分功能存在自然依赖,例如想要监听鼠标事件就必须初始化视频子系统以获取窗口; - 静态链接建议:虽然模块化支持在静态链接时剔除无用模块,但 Gordon 强烈建议开发者尽量采用动态链接。 ### [15:10](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=910s) 视频子系统的新特性与图形上下文管理 视频子系统是整个 SDL 2.0 最引人注目的部分。相比于旧版 SDL 1.2 仅支持单个窗口的硬性限制,SDL 2.0 彻底解除了束缚,全面支持多窗口与多显示器管理。当用户的电脑连接了多台显示设备(例如三屏联播)时,SDL 能够枚举所有显示器,获取它们在虚拟桌面空间中的绝对物理坐标、各自支持的分辨率和刷新率显示模式,并允许开发者在不同屏幕上创建独立窗口,或者在同一屏幕内平铺多个窗口,这极大拓展了 SDL 在大型复杂工具或非游戏类应用中的使用场景。 在窗口内容绘制方面,SDL 给予开发者充分的自由: - 渲染 API 随意挑选:支持传统软件渲染、纯正 OpenGL、OpenGL ES 以及 Direct3D; - 贯彻“不添乱”原则:SDL 的首要目标是帮开发者拉起窗口并理清底层句柄,随后立刻“退居幕后”,让开发者直接调用选定的原生图形 API; - 简化 OpenGL 上下文管理:彻底消除了直接调用平台原生 GLX 或 WGL 时晦涩复杂的模板逻辑,仅需几行简短调用设定颜色深度等基本属性,再发起一次上下文创建请求即可; - 丢失上下文(Lost Context)应对:针对观众提出的 Direct3D 与 OpenGL 上下文丢失处理机制,Gordon 说明 Direct3D 会直接暴露底层 Device 供开发者自行检查,而针对 OpenGL 上下文丢失的内部处理机制当时已在开发管线中,计划在后续版本发布。 ### [16:55](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=1015s) SDL 的开销表现与 Video API 基础概念 在台下观众提问 SDL 的性能开销究竟如何时,Ryan Gordon 回应称这正是一个绝佳的问题。他明确解释道,SDL 的开销仅仅相当于“一两次函数调用”。SDL 本身大部分时间都保持克制、不干预业务,它的本质是一个极薄的抽象层(thin shim),作用就是探测当前平台的需求并直接转发到原生平台调用。它内部甚至没有堆砌一长串 `if` 条件分支去反复判断“当前运行的是 Wayland、X11 还是 Raspberry Pi”,而是全部通过函数指针直接跳转到目标实现上。因此,使用 SDL 所产生的开销在性能分析器(Profiler)中根本微不足道,甚至完全检测不到。Ryan Gordon 总结道:“在函数调用和 CPU 时间方面,SDL 的开销是极低的(the overhead for SDL is incredibly low in terms of like function calls and CPU time)。”真正会在性能分析中体现出耗时的,通常是系统级操作(例如 OpenGL 交换帧缓冲),但这属于显卡与系统的固有开销,无论是否使用 SDL 都会存在。 回到 Video API 本身,它负责向外暴露各类 GUI 事件,例如鼠标悬停、窗口失焦等典型操作系统事件,免去了开发者自行处理 Windows 消息循环的繁琐工作。此外,SDL 还提供了一个看似微不足道但至关重要的特性——系统消息框(Message Boxes)。跨平台弹出一个错误弹窗在很多系统上实现起来异常棘手,“你可能会感到极其意外,所以我们提供了一个 API,专门帮你搞定在屏幕上显示一个错误对话框”,这属于关键时刻能拯救开发者的单次函数调用。紧接着,Ryan 梳理了 Video API 中几个核心的图形概念: - **Window(窗口)**:即屏幕上带有标题栏的标准实体窗口,可设置是否允许调整大小、是否最大化或是否有边框等。 - **Surface(表面)**:位于系统内存(System RAM)中的 2D 像素缓冲区。在 SDL 1.2 时代,除了少数通过 DirectDraw 强行推入显存的特例外,Surface 基本都在 CPU 侧。在 SDL 2.0 中,凡是放在内存里的像素缓冲统一称为 Surface。 - **Texture(纹理)**:位于显存(Video RAM / GPU Memory)中的像素缓冲。 - **OpenGL 与 Direct3D 支持**:SDL 团队投入了巨大精力确保 OpenGL 跨平台体验的一致性。对于倾向使用 Direct3D 的开发者,SDL 同样完全支持,可以直接向开发者提供 Direct3D 渲染设备对象,或者直接交出原生窗口句柄(Window Handle),交由开发者自由处置。 ### [19:20](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=1160s) 2D Render API:为现代平台重塑复古与轻量级游戏 针对 2D 场景,SDL 2.0 引入了一套轻量级的 2D 渲染 API。Ryan Gordon 生动地将其形容为“你所见过的最强劲的超任(the most hyped up Super Nintendo you've ever seen)”。这套 API 的设计逻辑是将资源加载进显存,像处理精灵(Sprites)一样自由绘制、缩放与旋转。它的定位非常明确:绝非为了与 OpenGL 正面竞争;如果游戏有更高、更复杂的图形诉求,开发者应当直接转向 OpenGL。然而,若是制作《超级马力欧》风格的克隆作品、轻量原型,亦或是无需繁重 3D 渲染的高品质商业级游戏,该 API 则是绝佳之选。它直接利用驻留在显存中的纹理进行极高效率的屏幕位图传输(blit),支持基础的 Alpha 混合、绘制线段与矩形等几何图元、纹理旋转缩放,以及基础的颜色调制。 更重要的是,这套 API 能让老旧经典游戏重新焕发生机。许多游戏公司手握 1990 年代 DirectDraw 兴起时期发行的顶级 2D 游戏,Ryan 表达了强烈期盼:“我非常希望在 Steam 上看到这些游戏,非常希望能看到这些游戏得到翻新(I would love to see those games on Steam; I would love to see those games updated)。”利用 2D Render API,开发者可以轻而易举地将老旧的 CPU 软件渲染器迁移至现代 GPU 上,从而直接获得 Steam 游戏内覆盖(Steam Overlay)支持,并在现代高分辨率显示器上实现无损缩放,摆脱以往只能缩在“邮票大小”窗口里运行的窘境,诸如《毁灭公爵 3D》(Duke Nukem 3D)这类的经典作品都能借此技术获得新生。 ```mermaid flowchart TD accTitle: 2D Render API 升级路径 accDescr: 展示老旧 2D 游戏如何通过 SDL2 Render API 从软件渲染平滑过渡至 GPU 硬件加速并获得现代平台特性的流程 subgraph Legacy["传统模式 (Legacy / SDL 1.2)"] A["CPU 软件渲染"] --> B["内存 Surface 缓冲区"] B --> C["窗口呈现 (无 Overlay / 缩放受限)"] end subgraph Modern["现代模式 (SDL 2.0 Render API)"] D["游戏逻辑 / 图元指令"] --> E["GPU 显存 Texture"] E --> F["硬件加速渲染 (旋转 / 缩放 / Alpha 混合)"] F --> G["多平台呈现 + Steam 覆盖层完美支持"] end B -.->|"迁移至 SDL2"| E ``` ### [20:58](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=1258s) 实战案例:《地下城决战》的零代码改动跨平台奇迹 为了佐证 2D Render API 的威力,Ryan Gordon 以 Gaslamp Games 旗下的知名 Roguelike 游戏《地下城决战》(Dungeons of Dredmor)为例进行了现场展示(台下刚好坐着该游戏的开发者 Nicholas)。这款游戏包含大量在屏幕上移动的 2D 精灵,原本是在 CPU 侧直接向帧缓冲写数据的传统 2D 架构。由于 Steam 覆盖层(Overlay)必须依赖 OpenGL 或 Direct3D 才能运作,该作原先在 Windows 上一直面临覆盖层无法呼出的顽疾。团队将其移植至 SDL 2.0 作为技术验证,把所有的精灵位图全部转化为显存纹理,直接在 GPU 上跑渲染,不仅彻底解决了 Windows 上的 Steam 覆盖层问题,还让 Mac 版本获得了同样的硬件加速。 紧接着,团队探索了 SDL 的可移植性边界。由于渲染逻辑已完全转由 GPU 处理,哪怕在算力较弱的移动设备上进行带有透明混合的位图搬移也毫无性能压力。他们尝试将游戏直接部署到 iPad 上,结果令人惊叹:除了接入 SDL 2.0 本身的工作外,针对移动端的代码改动量为“零行代码”(Total lines of code changed for this: zero)。不仅如此,iOS 上的触控事件在未做专门定制时会自动向下兼容映射为鼠标点击,因此游戏底层完全误以为自己在跟普通鼠标交互,直接就能用手指在屏幕上流畅操作。随后 Ryan 展示了更极端的案例——直接把该游戏运行在连接着电视的树莓派(Raspberry Pi)上,同样是零行代码改动(台下的 Dreamcast 主机则尚未成功运行)。在此 Ryan 还特别代 Gaslamp Games 作出免责声明:“Gaslamp Games 让我向各位澄清,他们目前并不会正式发售这个版本……千万别跑到他们门前催着要树莓派移植版。” ### [23:05](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=1385s) OpenGL 上下文接入与底层事件循环 对于追求极限制图表现的项目,Ryan Gordon 展示了在 SDL 2.0 中调用 OpenGL 的极简工作流。他风趣地为之前声称“不会放代码”自嘲是“从头到尾的伪善者”,并给出了极度精炼的代码逻辑: 1. 调用 `SDL_CreateWindow` 创建基础窗口; 2. 调用 `SDL_GL_CreateContext` 传入该窗口以生成 GL 上下文; 3. 执行具体的 OpenGL 渲染管线; 4. 调用 `SDL_GL_SwapWindow` 将渲染内容推入屏幕呈现。 在演讲过程中,坐在一旁的 Sam Lantinga 进行了提示,Ryan 随即纠正了自己刚才看似将 OpenGL “过于轻描淡写”的说法。他强调,在 `SDL_GL_CreateContext` 和 `SDL_GL_SwapWindow` 之间的注释区域,开发者拥有完整的图形自由度:“你可以把《孤岛危机 12》(Crysis 12)写在这里,也可以把虚幻引擎 14(Unreal Engine 14)写在这里。”事实上,诸如《军团要塞 2》(Team Fortress 2)、《止痛药:地狱与诅咒》(Painkiller: Hell & Damnation)以及《英雄萨姆 3》(Serious Sam 3)等高画质 3D 商业大作的完整图形渲染逻辑,全部都是严丝合缝地嵌在这两行 SDL 调用之间运行的。此外,SDL 针对 OpenGL 扩展探测提供了极其简洁的封装:开发者只需传入一个扩展名称的字符串发起单次函数调用,SDL 就会返回该扩展是否受支持,方便程序决定是否启用最新的高级着色器功能。 最后,Ryan 快速切入到事件处理(Events)。无论是鼠标划过、键盘敲击,抑或是用户调整窗口尺寸(开发者亦可直接禁用缩放),SDL 将所有来自底层窗口系统的交互行为规整成高度精简的统一轮询机制(Event Loop),开发者只需调用 API 依次获取事件队列中的下一项,并通过判断事件类型(如鼠标移动、按键按下、窗口关闭请求)即可完成全部输入分发。 ### [25:27](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=1527s) 跨平台事件系统、触摸支持与定时器 Ryan Gordon 解释道,SDL 2.0 的事件循环设计极其精简,却能屏蔽底层平台的复杂差异。无论开发者是在面对标准的 Windows 消息循环,还是面对 Mac OS 上的 Cocoa 事件循环,SDL 都会在底层统一处理并将其转化为抽象的 SDL 事件,开发者编写的代码在所有平台上无需变动一行。除了常规的按键和窗口大小调整事件,SDL 2.0 还内置了触摸 API(Touch API),支持 Android 和 iOS 等移动设备的触屏交互。 ```mermaid flowchart TD accTitle: SDL 2.0 跨平台事件与触摸抽象架构 accDescr: 展示底层系统事件如何经由 SDL 2 抽象为统一事件或转译为触摸/手势事件 subgraph OS_Inputs ["底层平台事件源"] WinMsg["Windows 消息循环"] CocoaMsg["macOS Cocoa 事件循环"] TouchDev["移动端屏幕触摸 (iOS / Android)"] end subgraph SDL_Core ["SDL 2.0 事件抽象层"] EvLoop["统一事件循环 (SDL_Event)"] TouchSys["触摸系统 / 鼠标模拟"] Gestures["$1 手势识别引擎 (Dollar Gestures)"] end subgraph Game_Code ["游戏逻辑层"] MouseEvent["普通鼠标代码 (透明兼容)"] MultiTouch["多指触控逻辑"] GameAction["游戏交互响应"] end WinMsg --> EvLoop CocoaMsg --> EvLoop TouchDev --> TouchSys TouchSys -->|"默认转译 (标记为来自手指)"| MouseEvent TouchSys -->|"多指追踪"| MultiTouch TouchSys --> Gestures Gestures -->|"匹配预设轨迹"| GameAction EvLoop --> GameAction ``` 为了兼顾不同开发者的诉求,SDL 对触摸事件采取了灵活的兼容设计:默认情况下,触摸事件会伪装成鼠标事件发送,但在事件内部会明确标记“这其实来自一根手指”。如果游戏不关心触摸逻辑,直接沿用原有的鼠标代码即可;若需要高级触摸操作,SDL 支持同时追踪多根手指,并集成了名为“Dollar Gestures”($1 手势)的识别系统,允许开发者录制简单的滑动手势,当玩家在屏幕上划出特定轨迹时直接向游戏触发事件通知。此外,SDL 还提供了简易的定时器(Timer)API,开发者设定每隔 $X$ 毫秒触发一次回调,系统便会向常规队列压入一个专用的定时器事件。 现场有观众询问 SDL 是否支持 Steam 控制器(Steam Controller)以及移动端(iOS / Android)手柄: - **Steam 控制器**:Ryan 明确表示不支持通过 SDL 游戏手柄 API 访问,“因为 Steam 控制器在操作系统看来就像是鼠标和键盘,所以针对该控制器你必须使用 Steamworks API”。 - **移动端手柄**:Android 的手柄支持刚刚并入代码库;iOS 方面,由于直到 iOS 7 苹果才首次推出正式的手柄 API,SDL 尚未支持早期第三方外设(如 Atari Arcade),但针对 iOS 7 官方 API 的适配已在规划中,预计会在下一版本实装,届时开发者无需修改代码即可自动获得支持。 --- ### [28:10](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=1690s) 原生适配、授权协议与平台打磨 一位参与过《博德之门》(Baldur's Gate)重制版开发的现场观众提出反馈:他们在一年前使用 SDL 2.0 移植时,虽然通过 SDL 获取基础触摸事件,但诸如双指捏合(Pinch-to-zoom)缩放等滑动交互最终还是绕过 SDL 直接调用了 iOS 原生系统 API。Ryan 肯定了该作的品质,并承认一年前至今 SDL 经历了大刀阔斧的演进,处理能力已有提升,但也诚恳指出了跨平台开发的现实边界。 Ryan 谈到,尽管此前演示了《地下城军团》(Dungeons of Dredmor)在 iOS 上零代码改动即可运行,但移植并不意味着可以偷懒放弃针对特定平台的优化。为解决移动端适配的法律障碍,SDL 2.0 将授权协议从 LGPL 改为了 Zlib 许可证,使得在 iOS 上静态链接 SDL 不再触碰合规红线。然而,开发者依然需要花费精力打磨细节:“尽管我们让你具备了可移植性,但你依然需要付出自己的打磨,首先得让它成为一个出色的程序。” - **消除移植糙感**:移动端玩家希望应用像一个地道的 iPad App,而不是一款粗糙的移植作;同理,PC 玩家极度反感 Windows 游戏界面上残留 PlayStation 手柄的按键图标。 - **合理分层**:跨平台底层(SDL)负责抹平设备驱动和窗口创建的脏活,而上层交互(平台特有的手势习惯、按键提示 UI)需要开发者主动适配各平台的文化与标准。 --- ### [29:55](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=1795s) 底层摇杆 API 与 DirectInput 的历史痛点 在控制器架构上,SDL 2.0 提供了清晰的分层机制,首先是底层的摇杆 API(Joystick API)。该层级完全贴近操作系统的驱动反馈:只要操作系统能够识别(例如接入 16 个 USB 摇杆),SDL 就能全部接入并管理。它原生支持热插拔,能精准捕捉玩家怒退(Rage-quit)拔出控制器或是新玩家插上手柄加入对局的瞬间,从而方便游戏触发“有新挑战者加入”等响应。 开发者既可以按帧轮询(Poll)摇杆当前的状态快照(类似于 DirectInput 或 XInput 的方式),也可以选择让按键与摇杆动作转化为标准事件推入 SDL 事件队列。底层 API 允许程序查询摇杆轴(Axes)、按键(Buttons)、苦力帽(Hats)以及设备的硬件名称字符串(例如“Logitech Wingman 3D”)。 然而,Ryan 指出这种底层 API 在现实世界中极难驾驭。任何用过 DirectInput 的开发者都深知其痛苦:市面上存在数以万计的 USB 摇杆与山寨手柄,键位排布各不相同、轴映射千奇百怪。为了让游戏能够正常游玩,开发者往往被迫编写复杂的按键校准界面(Configuration UI),强迫玩家逐个按键映射,这种糟糕的用户体验在 PC 游戏领域困扰了行业多年。 --- ### [31:19](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=1879s) 游戏控制器 API(Game Controller)与按键抽象 为了解决输入碎片化的难题,微软通过 XInput 树立了一个极具启发性的标准:将所有手柄抽象为 Xbox 360 控制器形态。虽然微软采取了仅允许认证的 Xbox 360 手柄工作的排他策略,但这种将控制器标准化的思路彻底解放了游戏开发者——制作《超级马力欧》类型的动作游戏时,逻辑层只需关注“上、下、左、右、跳跃”,而无需关心物理硬件内部具体的电气针脚。 ```mermaid flowchart LR accTitle: SDL 2.0 游戏控制器映射分层架构 accDescr: 展示杂牌与多样化物理硬件如何映射为标准 Xbox 360 控制器模型 subgraph Physical_Devices ["物理硬件与适配器"] XboxPad["Xbox 360 / 原生手柄"] PS3Pad["PS3 等标准控制器"] CheapPad["杂牌 / 街头白盒手柄"] SNESAdapter["SNES 转 USB 转换器"] end subgraph SDL_Mapping ["SDL Game Controller 抽象层"] GUID["读取 USB VID / PID 与系统 GUID"] DB["内置硬件映射数据库"] CrowdMap["Steam 大屏幕模式众包映射表"] end subgraph Standard_Model ["标准控制器模型 (Xbox 360 标准)"] FaceButtons["ABXY 面键"] Sticks["双可下压摇杆 (L3/R3)"] Triggers["双扳机 + 双肩键"] SystemButtons["Start / Back / Guide"] end Physical_Devices --> GUID GUID --> DB CrowdMap -.->|"补充未知硬件配置"| DB DB --> Standard_Model ``` SDL 2.0 吸纳了这一思想的优势,摒弃了厂商锁定(Vendor Lock-in),构建了高层的“游戏控制器 API”(Game Controller API)。随着 AAA 乃至独立游戏几乎完全转向以 XInput 为蓝本开发,这套 API 满足了跨平台移植的刚需: - **统一硬件画像**:将所有控制器规范为具备标准按键布局的模型,涵盖 ABXY 四颗面键、两枚可下压的模拟摇杆、肩键、模拟扳机键、Start、Back 及 Guide 键。 - **硬件指纹识别**:通过读取 USB 供应商 ID(VID)、产品 ID(PID)以及操作系统生成的 GUID,识别手柄身份并映射至标准定义。即使是纽约街头小摊上由未知厂商制造、毫无品牌标识的低价手柄,只要具有合法的设备 ID,SDL 就能将其扳机与按钮自动对应到正确的逻辑键位上。 - **外接转接器兼容**:对于将超级任天堂(Super Nintendo)等复古手柄转接至 USB 的设备,只要数据库内有该硬件特征记录,便同样能够将其当作现代控制器使用。 - **众包映射数据库**:面对市场上无穷无尽的冷门控制器,单纯依赖开发者手工录入难以为继;为此,SDL 与 Valve 合作,通过 Steam“大屏幕模式”(Big Picture Mode)数以百万计的玩家群体众包手柄校准数据,构建起庞大的手柄硬件数据库。 ### [34:16](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=2056s) Steam 大屏幕模式与 SDL 手柄映射数据库 Ryan Gordon 详细阐述了 Steam 大屏幕模式(Big Picture Mode)与 SDL 之间的数据联动机制。当玩家在 Big Picture 模式下手动校准、配置某款手柄时,Steam 会在后台默默记录下这份按键映射并将其上传至 Valve。Valve 收集到足够数量的相同配置后,就能确认这是一种常见手柄的真实布局,而非个别玩家的恶作剧,进而将其收录为官方默认配置。这意味着,即使某位玩家首次插上一款从未配置过的第三方手柄,Steam 也能直接推测其类型,并在游戏启动时将精确的映射字符串注入到 SDL 中,实现即插即用。如果手柄极其小众未被收录,开发者或玩家也可以通过独立配置程序、环境变量或外置配置文件手动定义。这种配置形式实质上是一串看起来略显奇特的映射字符串,例如明确写明“当系统读到按键 1 时,代表手柄上的 X 键”。 ```mermaid flowchart TD accTitle: 手柄配置同步与映射流程 accDescr: 展示玩家在Steam Big Picture中配置手柄并上传至Valve,随后合并为默认预设分发至SDL的过程。 subgraph Cloud["云端收集与验证"] A["玩家在 Big Picture 校准手柄"] --> B["配置上传至 Valve 服务器"] B --> C{"样本量是否充足?"} C -- "验证非恶意数据" --> D["合并入官方手柄数据库"] end subgraph Runtime["运行时生效"] D --> E["启动游戏时注入 SDL"] F["玩家接入未知手柄"] --> E E --> G["游戏内统一映射为类 Xbox 手柄标准"] end ``` 相比微软强制推行、严重依赖 Xbox 360 外设的 XInput 体系,SDL 游戏控制器 API 既保留了手柄抽象的极简性,又打破了硬件壁垒,让许多原本无法正常识别的老旧设备重获新生。在 Windows 环境下,SDL 同样会在底层按需利用 XInput,若玩家插上原生 Xbox 360 手柄,无需开发者编写任何专门的 XInput 代码即可获得完美支持。面对观众席对于按键数量不匹配的提问(例如手柄按键多于或少于标准 Xbox 手柄),Gordon 坦率指出,控制器模型在设计上确实不如 DirectInput 那样允许任意探查硬件,但足以应付绝大多数主流游戏类型。正如 Ryan Gordon 所强调的那样:“如果你在写飞行模拟器,你绝对不想用这个;但如果你在写《超级马里奥兄弟》或者哪怕是《飞行俱乐部》,这才是你应该用的东西。” - 映射字符串本质为键值对应关系(例如特定驱动按键映射到虚拟的 Xbox 键位)。 - 支持通过环境变量或配置文件动态加载自定义映射规则。 - 随着数据库持续更新,各类奇异的复古外设(如 USB 接口的超任手柄)会不断被收录支持。 - 缺失的物理按键(如无扳机键)直接缺省,无法凭空生成事件;多余按键则需由玩家或开发者挑选映射。 ### [35:53](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=2153s) 力反馈(Haptic API)与多设备振动控制 随后,Gordon 介绍了 SDL 的 Haptic API,并风趣地调侃“Haptic”这个词要么源于拉丁语要么源于希腊语,总之代表力反馈(Force Feedback)。现场有观众试图提出具体的代码实现故障,Gordon 建议留在台下讨论,并打趣道:“任何软件里其实都会有 Bug,所以这完全有可能是我们的错,我们会修好的。”该接口不仅支持常见的震动游戏手柄,还涵盖了某些平台上特定的力反馈鼠标(如会按指令震动的神奇罗技鼠标)。 在控制精度上,Haptic API 提供了从底层波形到极简震动的广泛选择。开发者既可以像使用 DirectInput 力反馈模型那样,先查询硬件是否支持正弦波(Sine wave)、方波(Square)或三角波(Triangle)等复杂物理参数并分别编程;也可以采用简单粗暴的“即发即弃”(Fire-and-forget)模型,只设定振动强度与毫秒持续时间(例如持续振动 3000 毫秒后自动停止)。底层系统会在后台独立线程中维持震动,绝对不会阻塞游戏主循环。针对主流手柄的双马达结构,该 API 同样支持对左右两侧不同配重的马达进行独立驱动。Gordon 感慨道,过去很多年因为缺少这套接口,他在把商业游戏移植到 Linux 时不得不将力反馈代码全部打桩抽空(Stub out),现在终于能在移植版中让设备尽情震动了。 ### [38:56](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=2336s) 音频 API:不加修饰的底层 PCM 数据流 转向音频子系统时,Gordon 立即给全场打了一剂预防针:SDL 的音频 API 极其底层,其运作方式相当于直接操作 DirectSound 的 DMA 缓冲区,甚至可以将其形容为“无休无止的 PCM 数据流”(a relentless stream of PCM)。正因如此,他并不建议普通游戏逻辑直接对接该接口,它更适合引擎底层开发者、需要自己编写混音器(Mixer)或拥有独立 3D 空间音频管线的团队。该 API 仅负责将预先处理好、预先混音完成的原始未压缩 PCM 数据泵入声卡硬件。 SDL 音频在格式兼容性上极其完备: - 声道支持:涵盖单声道(Mono)、双声道立体声(Stereo)、四声道(Quad)、5.1 环绕声,并即将加入 7.1 支持。 - 采样格式:涵盖 8 位、16 位、32 位整数(支持有符号与无符号、大端序与小端序),以及单精度浮点数(Floating point)。 - 格式自适应:macOS 的 CoreAudio 偏好浮点输入,而老旧平台(如 Windows 3.1 时代的 WaveOut)偏好整数;游戏只需交付自己能生成的数据格式,SDL 会在后台完成即时格式转换(On-the-fly conversion)与重采样(Resample)。 在架构设计上,音频驱动依赖回调函数机制驱动。SDL 会自行拉起一个独立线程,只要硬件缓冲区见底需要更多音频,就会触发该回调向开发者索取数据。Gordon 笑着回忆道,在极其古老的 Mac OS Classic 时代,为了喂饱音频,SDL 甚至直接在硬件中断(Hardware interrupt)里执行这个回调函数,那真是一件让人胆战心惊的危险举措。对于普通团队,Gordon 强烈建议直接接入更高阶的库,如开源的 SDL_mixer、OpenAL,或是 FMOD、Miles Sound System 等商业中间件,而把原生的底层音频接口交给引擎内部去调度。 ### [41:16](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=2476s) 跨平台线程与原子操作 面对紧张的演讲倒计时,Gordon 快速进入了多线程 API 的剖析。函数 `SDL_CreateThread` 在行为逻辑上极其直观,它在内部对各平台原生的线程生成函数(例如 Windows 上的 `CreateThread` 和 Linux 上的 `pthread_create`)进行了跨平台封装。然而它包含了一个大部分原生 API 所不具备的实用特性:开发者可以在创建时为其传递一个显式的字符串作为线程名称。SDL 会通过一些极为晦涩的底层“黑魔法”(Black Magic),将该名称注入到操作系统核心中,让其在宿主调试器(Debugger)的线程列表中清晰可见。当项目并发规模达到上百个工作线程时,这个功能让开发者能瞬间定位排查目标,极大减轻了调试负担。 除了标配的互斥锁(Mutexes)、信号量(Semaphores)以及条件变量(Condition variables)外,Gordon 重点强调了 SDL 所提供的原子操作(Atomic operations)。自己手写无锁并发或者比较并交换(Compare-and-swap, CAS)逻辑一向令人望而生畏,且极其容易滋生与编译器优化、硬件架构深度绑定的平台专用代码。SDL 为此封装了跨平台的通用原子操作函数,如针对指针或 32 位整数的 `SDL_AtomicCAS`;若宿主操作系统本身提供了原子机制,SDL 便直接对接,若无,则会在底层回退到针对特定 CPU 架构和特定编译器的专用汇编指令集(Op codes)。 ### [42:28](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=2548s) 动态链接库的统一载入 在演讲尾声,Gordon 提到了日常工程中极其普遍却繁琐的动态库加载问题。几乎每一个涉及跨平台动态链接库(DLL/SO/Dylib)调用的 C/C++ 项目,源码里都充斥着大量丑陋的条件预编译宏指令(`#ifdef`)。开发者往往需要先写 Windows 下的 `LoadLibrary`,再写适配 Linux 的 `#elif` 搭配 `dlopen`,甚至还要兼顾 BeOS 等小众操作系统的奇特接口。SDL 同样对此类通用平台差异进行了规整,为动态库的运行时加载与符号导出提供了简洁一致的封装,消除了项目中四处散落的平台宏分支。 ### [42:51](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=2571s) 动态库加载与原生对话框的跨平台封装 Ryan Gordon 首先介绍了 SDL 2.0 对动态链接库加载的抽象。开发者面对底层平台时总会遇到不同的接口,而在 SDL 中逻辑被统一为两步:告诉它你想打开哪个库,SDL 自动处理平台差异;接着查找指定符号,SDL 会直接返回函数指针,若未找到则返回 `NULL`。 随后他谈到了系统消息对话框(Message Boxes)。在 Windows 上调用原生消息弹窗十分简单,但在 Linux/X11 环境下并没有现成且方便的原生对话框函数。SDL 对此进行了兜底:若运行环境缺乏原生机制,它会直接自行构建一个窗口并绘制成用户熟悉的弹窗样式,免去开发者自己编写 GUI 的烦恼。Ryan 风趣地调侃这种弹窗的用途:“有时你就是需要说:‘一切都完蛋了,我正打算上报这个游戏,我很抱歉’,这就是消息框的作用。”(“sometimes you just need to be like everything's broken I'm about to report this game I'm sorry um and that's what a message box is for”) - **动态库加载**:统一跨平台动态链接库打开与符号查找(`dlsym` / `GetProcAddress` 统一抽象)。 - **消息弹窗**:Windows 提供原生接口;在 X11 等缺乏现成弹窗机制的环境下,SDL 会主动自绘一个原生风格的弹窗窗口。 --- ### [43:30](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=2610s) 剪贴板、底层兜底接口(SysWM)与 CPU 特性检测 在剪贴板操作方面,SDL 提供了统一的获取与设置接口,由底层根据不同平台自动实现。针对那些极端特殊的需求,SDL 提供了名为 `SysWM` 的后备机制。在最棘手的情况下,开发者可以通过该接口直接提取底层平台特定的窗口句柄(如 Win32 的 `HWND`)或其他原生对象。虽然这意味着代码中会出现 `#ifdef`,但 Ryan 强调 SDL 绝不向开发者死板地封死底层通路:如果你必须使用平台专属的 Win32 API,“这就是给你的钥匙”。 CPU 特性检测模块允许开发者在运行时查询当前 CPU 支持的指令集架构,包括 SSE、MMX、或者旧款 Mac 上的 AltiVec 等指令集支持情况,甚至包括处理器时钟频率的汇报,方便开发者针对性地开启矢量化优化。 --- ### [44:15](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=2655s) 标准 C 运行时替代方案与内存分配机制讨论 在标准 C 运行库(C Runtime)方面,SDL 对常用函数进行了全套替换。由于早期 Visual Studio 缺乏安全的 `snprintf`,仅提供极易造成缓冲区溢出的 `sprintf`,而 `snprintf` 在 Linux 上表现良好,SDL 选择提供自己的统一封装。更重要的是,在 Windows 平台下,SDL 编译时完全不动态链接 C 运行时库,包括 `malloc` 在内的所有基础设施均由 SDL 自行实现。这样彻底规避了游戏与不同版本 MSVCRT 链接时引发的运行时冲突。 现场有观众提问是否可以直接对接系统级分配器,Ryan 解释道,目前内部并没有开放自定义分配器回调(Allocator Callback),`SDL_malloc` 始终执行内置逻辑。他转头询问台下的 SDL 创始人 Sam Lantinga 在 Windows 上具体是如何处理的,并引起一阵笑声。Ryan 随后确认 SDL 在底层是直接调用 Win32 API 申请内存的,且并未提供重载接口。不过该分配仅作用于 SDL 内部资源,开发者在自身代码中可以自由选择是否调用 `SDL_malloc`。Ryan 认可这个建议,表示“也许我们会在 2.1 里加上它,这其实是个不错的点子”。 - **C 运行时隔离**:提供 `SDL_snprintf`、`SDL_strcmp` 等一致实现;Windows 下不链接 C Runtime。 - **内存分配实现**:Windows 端直接通过 Win32 API 分配,内部尚无全局自定义分配器回调(计划后续版本考虑)。 --- ### [46:07](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=2767s) 抽象 I/O(RWops)、跨平台路径规范、电源管理与断言 在文件与系统抽象层,SDL 提供了多项极为实用的基础设施: ```mermaid flowchart TD accTitle: SDL2 系统与资源抽象层架构 accDescr: 展示 RWops 数据抽象流向、标准路径定位、电源状态查询以及跨平台入口点 sdlmain 的工作方式 subgraph RW["SDL_RWops 数据抽象"] SRC["数据源 (文件 / 内存缓冲区 / 网络流)"] --> RWOPS["SDL_RWops 函数指针接口"] RWOPS --> AUDIO["音频解码 (如 WAV 加载) 等内部子系统"] end subgraph OS_ENV["操作系统交互与规范"] FS["标准路径定位: 安装目录 & 用户存档路径"] PWR["电源检测: 电池电量 / 剩余运行时间 / 插电状态"] ENT["sdlmain: 抹平 WinMain 与 main(argc, argv) 差异"] end ``` Ryan 详细阐释了 `SDL_RWops` 的设计理念:它是一个面向流的抽象接口,本质上是一组函数指针结构体。例如在音频层加载 WAV 文件时,SDL 接收的是 `RWops` 而非裸文件指针(`FILE*`)。无论数据是从磁盘文件、内存块还是网络管道流入,接口均保持一致。在文件系统路径方面,针对以往 Windows 游戏开发者随意存放存档、而 Linux/macOS 严格隔离权限的现象,SDL 提供了标准的路径探测 API,可直接获取游戏的安装目录以及受操作系统保护的用户存档目录。 此外,SDL 还内置了电源管理查询接口,可实时汇报设备是处于交流供电还是电池供电,以及电池电量百分比和剩余使用时长,这在移动端和笔记本场景下对于节省功耗至关重要(台式机则直接返回无电池)。关于断言机制,Ryan 赞叹 SDL 内部拥有一套功能极强的高级断言宏,远胜于标准 `<assert.h>`,他打趣说:“当我们写出这套代码时,天使都在歌唱与落泪。”(“The Angels Sing and weep when we code this thing”)最后,可选模块 `sdlmain` 在 Windows 端替开发者封装了繁琐的 `WinMain` 入口,让跨平台代码无论在哪个系统上都能沿用统一的标准 `int main(int argc, char *argv[])`。 --- ### [48:06](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=2886s) SDL 2.0 未来演进蓝图与重大新特性预告 进入演讲尾声,Ryan 展望了 SDL 正在推进和规划中的诸多重大前沿特性。他强调这些虽不是严格的交付承诺,但团队正在全力实现: ```mermaid flowchart LR accTitle: SDL 2.0 近期演进特性规划 accDescr: 归纳音频、输入、显示服务器、移植与兼容性等方面的开发规划 subgraph INPUT_AUDIO["输入与多媒体采集"] MICE["多鼠标支持 (API 就绪,后端对接中)"] CAP["音频与视频采集 (麦克风 / 摄像头)"] SURROUND["7.1 环绕声输出支持"] end subgraph DISPLAY["现代显示协议与实验移植"] WAYLAND["Wayland 支持 (已合入 Mercurial)"] MIR["Mir 显示服务器适配"] WIIU["libdrc Wii U GamePad 串流实验"] end subgraph COMPAT["平台合规与生态兼容"] WINRT["Windows RT / Windows Store 认证支持"] S12C["sdl12-compat (1.2 API 无缝转发 2.0)"] DYN["Dynamic API (支持静态链接下热替换)"] end ``` 在输入与多媒体方面,SDL 已经定义了多鼠标(Multiple Mice)API,旨在让多名玩家在同一台电脑上各插一只鼠标进行本地对抗,目前正在完善各平台后端;麦克风音频采集与摄像头视频采集 API 也已排入日程;同时还将原生支持 7.1 声道环绕声。 在视窗协议与平台兼容方面,Linux 的 Wayland 支持已经合入 Mercurial 版本库,Mir 支持也即将推出。Ryan 还分享了自己编写的侧面趣味项目 `libdrc`,可以将 PC 画面直接串流推送到 Wii U GamePad 上手柄游玩(如直接串流玩《超级食肉男孩》)。针对微软生态,Windows RT 以及满足 Windows Store 应用商店上架认证的兼容补丁正在等待合并。 最受老项目关注的是 `sdl12-compat` 包装层,它将提供原汁原味的 SDL 1.2 导出接口,但底层全部重定向给 SDL 2.0 处理,使得老旧商业游戏甚至无需重新编译即可享受现代系统的全屏、多显示器与驱动优化。此外,创新的 Dynamic API 机制允许游戏即便静态链接 SDL,也能在未来通过外部动态库实现静默热替换升级。Ryan 热情邀请开发者提出需求与反馈:“如果你们有任何能改善游戏开发者体验的构想,我们非常乐意与你们交流。” --- ### [50:06](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=3006s) 社区支持资源、自动化测试流水线与答疑闭幕 在演示的最后一张幻灯片中,Ryan 介绍了 SDL 强大的基础设施与社区支持渠道。社区不仅拥有双向同步的邮件列表与 Web 论坛,还维护着内容完备的 Wiki 文档。在问题追踪方面,团队在 Bugzilla 上已经排查并修复了超过 2000 个 Bug,对工单进行着严格的宗教般(religiously)的跟踪审查。 为了保障各平台的代码质量,SDL 部署了 Buildbot 持续集成流水线,任何一次代码提交都会立即触发大约 14 个不同操作系统的自动化交叉构建;一旦某平台编译受损,机器人会立刻大声报警。Ryan 借此强调:“我们对待跨平台支持的态度是极其、极其严肃认真的。”(“we take crossplatform support very very seriously”) 演讲在此告一段落。由于在演讲过程中已穿插回答了观众提问,时间已基本耗尽,Ryan 邀请大家移步台下继续自由交流。在全场的掌声中,他留下了自己的联系方式(邮箱、Twitter 及 Google+),并不忘最后开了一句玩笑:“如果你现在还在用 Facebook 的话,伙计,你真该好好重新审视一下自己的人生了。”(“if you're still using Facebook man it's time to reevaluate your life”) - **社区与文档**:邮件列表与 Web 论坛双向打通,配有维护详尽的开发者 Wiki。 - **质量保障体系**:Bugzilla 解决超 2000 个缺陷;Buildbot 针对每次提交自动覆盖约 14 个目标平台。 - **联系与演讲材料**:PPT/PDF 幻灯片通过 Steam Dev Days 官方渠道公开,现场开放后续线下交流。 ## Notable quotes > [07:47](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=467s) Android 和 iOS 是必须支持的,因为无论我们喜欢与否,总有一天我们所有人都会在移动设备上玩游戏。 — Ryan Gordon > [28:10](https://www.youtube.com/watch?v=MeMPCSqQ-34&t=1690s) 尽管我们让你具备了可移植性,但你依然需要付出自己的打磨,首先得让它成为一个出色的程序。 — Ryan Gordon ## Mentioned Ryan Gordon (Icculus), Sam Lantinga, Valve, Steam, Steam Dev Days, Simple DirectMedia Layer (SDL / SDL 2.0 / SDL 1.2), DirectX, Direct3D, DirectSound, DirectDraw, DirectInput, XInput, OpenGL, OpenGL ES, Loki Software, Humble Bundle, Gaslamp Games, Dungeons of Dredmor, Duke Nukem 3D, Baldur's Gate, Team Fortress 2, Painkiller: Hell & Damnation, Serious Sam 3, Super Mario, Pilotwings, Steam Controller, Steamworks, Steam Big Picture, Wayland, Mir, X11, ALSA, PulseAudio, WASAPI, CoreAudio, FMOD, OpenAL, Miles Sound System, SDL_mixer, Raspberry Pi, Haiku, Wii U GamePad, libdrc, sdl12-compat, Buildbot, Bugzilla ## Video description This talk will offer a high-level overview of Simple Directmedia Layer 2.0. It will cover the features of the library and how it can make your game easier to build, port, improve and maintain. Speaker: Ryan Gordon (Icculus) Slides (PDF): http://media.steampowered.com/apps/steamdevdays/slides/sdl2.pdf Slides (PowerPoint): http://media.steampowered.com/apps/steamdevdays/slides/sdl2.ppt [Source](https://www.youtube.com/watch?v=MeMPCSqQ-34)

Source quotes

[7:47] Ryan Gordon: Android 和 iOS 是必须支持的,因为无论我们喜欢与否,总有一天我们所有人都会在移动设备上玩游戏。 [28:10] Ryan Gordon: 尽管我们让你具备了可移植性,但你依然需要付出自己的打磨,首先得让它成为一个出色的程序。

Source quotes

[5:19] Ryan Gordon: It makes hard things easy, that's the simple part of Simple DirectMedia Layer.

Original transcript

[0:01] thank you for coming to game development [0:02] uh with sdl 2.0 uh please welcome to the [0:05] stage Ryan Gordon from [0:10] Ulus all right uh thank you very much [0:12] for coming um okay let me start the [0:15] little clock here so I don't talk super [0:16] fast again is it going maybe no it's not [0:20] okay we're gonna just go ahead and start [0:21] then oh there it goes okay um okay so my [0:23] name is Ryan this is a talk about simple [0:25] Direct Media layer to we'll have lots of [0:27] slides for you to look at okay so just a [0:30] few notes to get started here feel free [0:31] to interrupt at any time if you have a [0:32] question raise your hand I'll try not to [0:34] ignore you I can actually see cuz the [0:36] lights are not in my eyes this time um [0:38] if you ask something interesting we [0:40] might to have a totally different talk [0:41] and the slides will just abandon so [0:43] don't be afraid to volunteer if you have [0:44] something you want to ask about um these [0:46] slides will be at that URL um later [0:49] today I'm going to upload them as soon [0:50] as this talk is done um this is just a [0:52] highle overview today we're only going [0:53] to talk about what sdl can do to make [0:55] your life better uh we're not I don't [0:58] think there's a single line of code in [0:59] this entire [1:00] uh slide deck so don't panic about that [1:02] just try to walk out here understanding [1:03] what you can do and then you can you [1:05] know go home and do awesome things with [1:07] it and look at the documentation and [1:09] stuff like that um if you want to tweet [1:10] during this that's my Twitter handle I [1:13] will see it later if you say nice things [1:14] I'll smile if you say mean things I'll [1:16] probably cry and that might be worth [1:17] doing to me too um okay [1:20] so who am I my name's Ryan i port stuff [1:23] to Linux and Mac OS and you know the uh [1:27] toaster oven in your apartment I do [1:28] those for I do that for living I've been [1:30] doing it for 15 years I've done it for a [1:32] lot of big games a lot of little games [1:33] and a lot of everything in between um I [1:36] build tools when I'm not porting games [1:38] uh that make my life easier I'm not [1:40] going to talk about them today although [1:41] there's a lot of self-promotion I could [1:42] do if I felt like it but I'm not going [1:44] to because that's not what we're here [1:45] for I'm a freelance I do this for myself [1:47] I don't work for another company and [1:48] I've been doing it for 15 years uh just [1:50] to give you an idea this is what my [1:51] NASCAR jacket looks like um lots of [1:55] people lots of big companies lots of [1:56] little companies lots of games uh Etc [1:58] like that this is my biggest Cent right [2:00] now this is my daughter Olive um okay so [2:03] anyway enough about me sdl we call it oh [2:06] yes question are you the guy that uses [2:08] to Port everything everything I am one [2:10] of the guys that humble uses to Port [2:12] everything the one of the other big ones [2:13] is sitting right in front of you right [2:14] now um other on oh and the other one's [2:17] there oh we're all here it's like a [2:19] big cult or something okay um so anyway [2:23] simple Direct Media layer we call it sdl [2:25] just assume that media is part of the [2:27] second word so it's a three-letter [2:29] acronym simple Direct Media layer it's [2:31] our open source answer to direct X if [2:33] you were writing a Windows game from [2:34] scratch you would reach for direct X [2:36] probably you would you know want the the [2:38] video from it the audio functionality [2:41] from it etc etc depending on what uh [2:43] year you're developing your game in but [2:45] outside of windows in mac and Linux sdl [2:49] is very popular because they don't have [2:50] directex of course they have this is an [2:52] equivalent to it it doesn't it's not the [2:54] same syntax it's a different Library [2:56] it's not the same set of functions but [2:58] it will give you roughly access to the [3:00] same stuff in a much I think easier way [3:03] than DirectX does and and the fastest [3:05] way it can and to make and also the [3:06] development time fastest way it can uh [3:09] it's crossplatform it runs on darn near [3:11] anything um uh we're working with sdl2 [3:14] right now and we've cut back to some [3:15] more modern recent platforms the [3:16] previous version ran on everything from [3:18] Amigas to Dreamcast to Palm pilots and [3:21] uh things I haven't even thought of yet [3:23] you know uh just ridiculous numbers of [3:26] things and in the current generation it [3:27] runs on lots of stuff you actually care [3:29] about in 2014 uh it's powerful it's fast [3:32] it's easy uh it's also had 15 years of [3:34] development much like me um it's been [3:37] maintained and heavily enhanced and [3:39] improved and bug fixed for a decade and [3:42] a half now um many games have used it [3:44] many many games over the years millions [3:46] of Gamers all of valve's games are [3:48] shipping they use sdl the steam client [3:50] itself uses sdl for certain things uh [3:52] lots of other games you've probably [3:54] played if you played it on Mac or Linux [3:56] you almost certainly used sdl if you [3:58] played it on Windows you might have used [3:59] sdl [4:00] um if you uh okay so and the website for [4:03] it is wwwi libsdl uh all these links [4:07] will be on later slides and these slides [4:08] will be available for download too um [4:10] okay brief history of this it was [4:12] started by Sam lantinga who is sitting [4:14] in the audience there he is okay um he [4:16] started for a program called exeggutor [4:18] which was a Mac OS classic clone uh [4:21] emulator it would run things it was [4:22] awesome and um that's where it started [4:25] and it made just a nice easy way to get [4:27] this crossplatform way to get bits to [4:29] the screen stuff like that uh and then [4:31] Sam got hired by Loki and Loki [4:33] and all right there's Loki employees [4:36] here too Loki adopted sdl as kind of its [4:40] framework to build to Port games to [4:41] Linux with because what they did for a [4:43] living was Port games to Linux and they [4:44] spent a great deal of time and a whole [4:46] staff of Engineers spent time improving [4:48] and enhancing the framework um it's kind [4:50] of now a deao standard if you want to [4:52] write games on Linux this is probably [4:54] what you're using already and if it's [4:55] not it's what you should be using uh [4:57] we'll get into y later and we just [4:59] shipped this uh the past couple months [5:01] we shipped sdl 2.0 uh which is the new [5:04] hotness it has a lot of new features [5:05] we're not going to talk about sdl 1.2 [5:07] today except to make fun of it but um uh [5:10] 2.0 is what you should be using it's [5:12] open source it's freely available you [5:13] can download it and play with it right [5:15] now if you want not right now because [5:16] I'm talking but um okay so here's some [5:19] basic features you can expect from sdl [5:21] if you were to pick this thing up it [5:23] targets modern os's your Macs your uh [5:26] Windows your linuxes but also your ios's [5:29] and Androids and stuff like that um it's [5:31] a portable game framework if you write [5:33] something to Target sdl it will probably [5:35] just work across all these platforms [5:37] without much fuss uh depending on how [5:40] much sdl you put into it um it's got [5:42] multiple API targets which sounds like a [5:44] weird thing to say but let let's say [5:46] that you have well we'll talk about that [5:48] later it's important but I have a whole [5:49] slide about it uh it makes hard things [5:51] easy that's the simple part of simple [5:52] Direct Media layer um if you there's [5:55] lots of things that game developers do [5:57] and they cut and paste boiler plate [5:58] because it's just kind of hard to do and [6:00] hard to do well and it's solved it's [6:02] ugly code we like to take those things [6:04] make sure you don't have to write them [6:05] we took care of all that nonsense for [6:07] you and I'll show you what I mean in a [6:08] moment uh it's written in C if you're a [6:11] C++ programmer we don't judge you but uh [6:13] there's a lot of benefits to it being [6:14] written in pure c not the least of which [6:16] is when we started C compilers were even [6:18] awful and C++ compilers were even worse [6:21] but uh it lets us make it very easy to [6:23] plug in scripting languages uh there's a [6:25] very highly uh maintained python uh [6:28] interface for sdl that people like a lot [6:31] for example and that was made easier by [6:32] having C instead of C++ and you know if [6:34] you like Lua if you like you know you [6:36] name your favorite scripting language [6:37] there's an sdl binding for it and being [6:38] written in C help that uh it's licensed [6:41] under the ZB license um has anyone ever [6:44] read the ZB license before only one of [6:46] you it's a good thing I put it on a [6:48] slide um don't read this this won't be [6:51] on the test but I'll give you the basic [6:52] rundown of what this means [6:55] um more or less what this says is we [6:57] don't give you a warranty on it so [6:59] please don't SU if it breaks for you uh [7:01] we like if you tell people that you use [7:03] it but we don't legally require you to [7:05] and um you know don't take our name off [7:08] of it that's it that's the entire [7:09] license now the older version was under [7:11] the gnu lgpl and we removed all the code [7:14] from that we changed the license we made [7:16] sure we had permission to do this [7:18] because we found that the lgpl is really [7:20] really scary for developers and even if [7:22] you could use it with close Source stuff [7:24] it was questionable and people got [7:25] nervous about it this is it man this [7:27] fits on a poster card it fit on a [7:28] PowerPoint slide so we thought this was [7:31] much easier I was going to put the lgpl [7:33] license on here but it took 22 slides at [7:36] this font so I decided not [7:37] to um but basically what that says you [7:40] can download it you can modify it you [7:41] can statically link it you can do [7:42] whatever you want with it and we're [7:44] happy that it's useful for you because [7:45] it's been useful for us um so I [7:47] mentioned this runs on a bunch of [7:48] different platforms this is our [7:49] currently supported list of platforms [7:52] and this this varies from dayto day but [7:54] of course Linux Mac OS and windows are [7:55] the big three on the desktop we support [7:57] them all uh I do all my velopment on sdl [8:00] under Linux unless I'm specifically [8:02] focusing on a platform thing uh but we [8:04] also have people working on Windows and [8:05] Mac OS like it's they're all important [8:07] in functional platforms I put Unix up [8:09] there because like if you're still [8:10] running Solaris or you have FreeBSD or [8:13] something those are also supported um [8:15] Android and iOS because the mobile [8:17] market is where we're all going to do [8:18] our gaming someday whether we like it or [8:20] not um Haiku is actually a newer version [8:22] of BOS just to give you an idea we [8:23] wanted to keep it so we had flexibility [8:25] so we could show how portable this was [8:27] and of course the Raspberry Pi that [8:28] little $35 device it will actually run [8:31] on that and get openg glees support on [8:33] it uh other interesting places it pops [8:36] up in places is New Ports show up we [8:37] take them in and you know it's good it's [8:39] 64-bit clean it's endian clean you can [8:42] probably get to a new platform fairly [8:43] easily um it has a lot of subsystems now [8:47] for sdl 1.2 this this slide was eight [8:49] bullets this one is [8:51] 16 uh some of these I'm going to go over [8:53] and great detail for most of this talk [8:54] but just to give you an idea of what you [8:57] can do with sdl uh you know it handles [8:59] your video stuff how I get bits to the [9:01] screen how I create Windows how I manage [9:03] my windows how I get audio uh PCM data [9:06] to the audio card events like when you [9:08] click a mouse button or hit the joystick [9:11] or something like that it has a very [9:12] simple 2D rendering API if all you want [9:14] to make is a very simple game and I'll [9:15] talk about that in detail later um [9:17] joystick support a higher level game [9:19] controller support things so you don't [9:20] have to screw with the details of all [9:22] the weird joysticks you might see in the [9:23] field haptic support which is force [9:25] feedback um that handles a lot of [9:27] platform stuff that you've probably [9:28] written platform specific code for that [9:30] would be nice to rip out like you know [9:31] how do I load a shared Library you can [9:33] take that if def out of your program and [9:35] you know what kind of processor am I [9:36] running on does it have SS 4.2 support [9:39] things like that um it hand and things [9:41] like wrapping up threads and stuff like [9:43] that and how do I find out the laptops [9:45] running on battery Etc we're going to [9:47] talk about this stuff okay I said before [9:49] it has multiple API targets and oh yes [9:52] talking about for before you move on um [9:54] what do people do about Expo and PS4 PS3 [9:56] 360 uh I've uh we'll talk about that a [10:00] little later he asked you know what [10:01] about like consoles like Xbox and PS4 [10:03] and stuff like that um we don't have a [10:05] specific plan for that at the moment [10:06] we're we're thinking about how to solve [10:08] that problem um okay so multiple API [10:11] targets I I said this before and some [10:12] people were probably like I have no idea [10:14] what that string of words means so um if [10:16] you run on uh Linux right now and how [10:19] many of you are Linux users okay wow a [10:22] good portion of you that's great um as [10:24] you know you have an X server that is [10:26] used to do video but as you might know [10:28] there's also something coming called [10:29] Wayland And there's also something com [10:30] called Mirror which will change the way [10:32] that we talk to the video card and uh [10:34] hardware and stuff so if you were to [10:36] talk to X11 right now next year your [10:38] game may or may not work it may not even [10:40] start depending on how well Wayan and [10:42] Mir end up handling that uh and [10:44] certainly anyone that's been a Linux [10:45] user for a decade or more has found out [10:47] that no matter how you like to talk to [10:48] the sound card it changes every now and [10:50] then uh they come up with a new API so [10:53] uh what sdl does is it does not actually [10:55] link to any of these things it does not [10:56] link directly to xib it doesn't link [10:58] directly to Al for audio what it will do [11:01] is use DL open and for your windows [11:02] developers that's load Library um it [11:05] it'll look for the the shared libraries [11:06] the DLS on your system that might match [11:09] what uh a user has and it'll try to [11:11] figure out the best path to get to their [11:12] video card and their audio card and what [11:15] technologies available on that system [11:16] and it will do the right thing and if we [11:18] prefer to have whand but they only have [11:20] X11 we'll try Wayland and say oh there's [11:22] no Wayland support in the system and [11:23] move on to X11 the users know wiser your [11:26] game just came up in a window and played [11:27] like you'd expected to without you [11:28] having to think about it um and we do [11:31] that for all the subsystems in here [11:32] there is nothing that sdl links against [11:34] except the standard C runtime and on [11:35] Windows we don't even link against that [11:37] so um and and like I said I'm I'm I'm [11:41] sitting here poking at Linux but you [11:42] know every system has this sort of API [11:44] problem um on Windows if you like to [11:46] talk to the sound card the CH the way [11:47] you do it has changed many times over [11:49] the years you could have been doing wave [11:50] out or direct sound or X audio 2 or [11:52] maybe was sappi or you know whatever it [11:54] might change again in Windows 12 who [11:56] knows we'll find out um so the next [11:59] thing I talked about with this was that [12:01] how simple it was this is the simple [12:03] Direct Media layer um so I wanted to [12:05] give you a demonstration here how many [12:06] of your windows developers we're going [12:08] to change you all I'm glad you're at a [12:11] conference about Steam OS this is the [12:12] right place to be you're going to learn [12:13] a lot today if you've ever done direct [12:15] 3D and you've talked directly to direct [12:17] 3D without any sort of framework in [12:19] between handling it for you this is a [12:21] dirt simple direct 3D example of how to [12:24] get a window on the screen so you can [12:25] start drawing 3D stuff okay here we go [12:27] you ready [12:29] okay you got to get a window class and [12:32] you got to register that and then oh I'm [12:33] not done here hang on a second then you [12:35] got to see what kind of uh properties [12:37] the video card has and you get this uh [12:39] frame buffer format and you know that [12:41] refresh rate oh can it do 3D Hardware [12:43] we're not actually sure at this point if [12:44] you actually have a 3D video card um [12:46] let's see and then you got to do some [12:48] other stuff and uh let's see no okay now [12:51] we have a window now we actually have a [12:52] way to draw 3D on the screen that was [12:54] four slides and the font was getting [12:55] smaller and I did that ironically this [12:57] seems like a pathological case this is [12:59] actually how they recommend you do it in [13:01] the direct 3 3D documentation this is [13:04] not something I made up to make them [13:06] look bad uh but they make themselves [13:07] look bad because if you could actually [13:08] read this on this [13:10] slide there is no error checking in that [13:12] example this actually goes on much [13:14] longer if you have to check for failure [13:16] cases uh a look of disapproval about [13:18] that I'll give you the Shifty eye for [13:20] that here's the really hard sdl version [13:23] you ready for this there you [13:25] go that gets a window on the screen and [13:28] you are ready to start drawing 3D [13:29] content period Point Blank done um as [13:32] you can see there's a flag if you want a [13:33] full screen window that takes over the [13:35] whole desktop and you can just do you [13:37] know a window window if you prefer [13:39] that's a 640 x 480 window done with a [13:42] little title bar says hello so I I use [13:45] this as an example I don't mean to poke [13:46] find a direct 3D except it's incredibly [13:48] easy [13:49] but this is kind of how we built the [13:51] whole API so a lot of things that you've [13:53] looked at and said H give it to the [13:54] intern this is much easier and much more [13:57] satisfying as a programmer to work with [13:59] over time so uh I use that as an example [14:02] but the entire API is structured this [14:03] way and a lot of functionality question [14:05] you eror oh look of disapproval I don't [14:08] have any error checking that's true I [14:09] don't uh as an exercise to the viewer [14:12] you can add the two if statements here [14:14] um okay so you might have seen on this [14:16] slide we have sdl and it is that first [14:18] call and what this is I think the only [14:20] code in this whole demonstration so um [14:23] you can see there's a flag to it STL and [14:24] nit video you can also say I also want [14:25] the audio layer they're bit Flags you [14:27] just order them together and you you [14:28] pick the subsystems you want and you [14:30] ignore the subsystems you want so for [14:32] example if you're using some third- [14:33] party uh audio library like you have fod [14:35] in your uh thing or using openal or mil [14:38] sound system or something like that just [14:40] don't give us the the audio flag and we [14:41] won't try to even look at the audio [14:43] Hardware so um and there are some [14:44] exceptions to this some things are a [14:46] little weird like you if you want to get [14:47] like Mouse events of course you need to [14:49] have a window so you have to have the [14:50] video subsystem and they're clumped [14:51] together like that but for the most part [14:53] you can pick and choose what you want [14:55] and if you're statically linking you [14:56] don't even have to have those the parts [14:57] you don't want in your code but don't [14:59] statically link if you don't have to I'd [15:00] recommend you not anyway but you can [15:02] make it so it doesn't touch the hardware [15:03] so the other things you do want to use [15:05] like a third party audio library can do [15:07] it without us interfering um okay the [15:10] video API this is really kind of the [15:11] bulk of the exciting stuff because [15:13] pixels are pretty right um it's really [15:16] simple you get multiple windows multiple [15:18] displays if you have someone that has [15:20] three displays hooked up we can [15:21] enumerate them for you tell you you know [15:23] roughly where they're positioned in [15:25] Virtual space what different modes they [15:26] can be set to if you need to change the [15:28] resolution on any of them Etc like that [15:31] and you can put different windows on [15:32] different displays or different windows [15:34] on the same display if you want to have [15:35] a game with more than one window um this [15:37] is new for sdl2 and in sdl 1.2 you can [15:39] only ever have one window because that's [15:41] what most games want but sdl2 was about [15:44] removing those kinds of limitations so [15:45] now you have a lot of power you can [15:46] build some very complicated things that [15:48] aren't necessarily games on [15:51] sdl2 um it's there uh the way you draw [15:54] into that window you have lots of [15:56] options you can do software rendering [15:57] into it if you really want to but openg [15:59] G GLS direct 3D all we want to do is get [16:02] you a window on the screen and get out [16:03] of your way so you can use your [16:04] rendering API of choice um it makes open [16:07] G context manage context management easy [16:09] which is to say everything I just made [16:11] fun of with direct 3D there if you're [16:12] talking to wgl or GLX to get an open GL [16:16] context those things are also kind of [16:18] ugly but we actually make it one [16:20] function call we just say a couple of [16:22] function calls you set the basic [16:23] attributes you want and then you uh you [16:26] say I want like this much you know this [16:28] this color depth and stuff like that and [16:30] then you say give me a context and it [16:31] goes okay and it figures out all that [16:32] for you did you have a question does it [16:34] also L [16:37] cont um we have stuff in the pipeline [16:40] for that but it's not made into a [16:41] release version yet but it's some it's a [16:43] feature we're thinking of adding soon he [16:45] want to know if you could deal with lost [16:46] contexts in opengl and direct 3D [16:48] obviously we just give you the direct 3D [16:50] device and you can check that yourself [16:52] uh question I was going to ask about [16:54] five minutes ago when you mentioned it [16:55] ran what is the overhead like how [16:59] that's actually a really good question [17:00] the over he asked what the overhead was [17:02] for sdl and the answer is a function [17:04] call or two we mostly stay out of your [17:05] way and it's mostly a very thin shim [17:07] that figures out what the platform wants [17:09] and goes directly to those platform [17:10] calls it's not even like a whole [17:12] collection of if statements like was [17:13] this Wayland was it X11 was it a [17:15] Raspberry Pi they're all function [17:16] pointers we jump into the right one and [17:18] you know uh your overhead for using sdl [17:20] it won't even show up in a profile um [17:22] what will show up is perhaps when you [17:24] swap frame buffers as an open gel for [17:26] the system but that has nothing to do [17:27] with sdl you have that anyway so uh the [17:30] the overhead for sdl is incredibly low [17:32] in terms of like function calls and CPU [17:34] time um uh the video API let's get back [17:37] to this for one second uh the video API [17:39] exposes um gii events like when you [17:41] Mouse over things uh lose window Focus [17:44] you know the things you would expect to [17:46] have to do with like a Windows message [17:47] Loop or something like that it's it's [17:49] fairly simple I'll give you there is one [17:50] other piece of code in here I'll give [17:51] you an example of what that looks like a [17:53] little later on um and of course message [17:55] boxes which seems really silly to be [17:57] like we support message boxes is but [18:00] those are actually really hard to do on [18:01] some platforms you would be incredibly [18:03] surprised so we actually have an API [18:04] that will figure out how to get just an [18:06] error dialog on the screen if you need [18:08] one so um sounds ridiculous one function [18:10] call that will save your life okay [18:12] there's a couple of Concepts that go [18:13] with this video API windows are just [18:15] what you think they are they're windows [18:17] they're the thing on your screen with a [18:18] title bar you can set them to be [18:19] resizable or not maximiz or have a [18:22] border or not and stuff like that uh [18:24] surfaces are 2D buff uh buffers of [18:27] pixels that sit in system Ram uh this [18:30] was the only way we did things with STL [18:31] 1.2 occasionally you could force them [18:33] into video RAM for direct draw but [18:35] almost always they were on the CPU and [18:36] we just forced it if you need a buffer [18:38] of pixels they're always in video [18:39] they're always in system Ram now and we [18:42] call those surfaces if you want them in [18:43] video RAM we call them textures which is [18:45] I guess probably everyone does but um [18:48] and we have an API that uses that so you [18:50] can even if you have a 2d software [18:51] rendered game you can push everything to [18:53] the video card and we'll get to that in [18:54] a moment and then of course openg we [18:57] like openg [18:59] we've taken great efforts to make sure [19:00] that open gel Works across multiple [19:02] platforms with sdl if you'd rather use [19:04] direct 3D you are totally able to do [19:05] that we will give you a direct 3D uh uh [19:08] rendering device object or we can also [19:10] just give you the handle the native [19:12] handle to a window and you can do [19:13] whatever you want with it if it comes to [19:15] that um and then you have to have all [19:17] that boiler plate code I showed you [19:18] before let's talk about this render API [19:20] for a moment we have a very simple 2D [19:23] rendering API um and I say this you [19:25] should think of this as the most hyped [19:28] up Super Nintendo you've ever seen um [19:31] it'll do think of it you can get things [19:33] into video RAM and then treat them like [19:35] Sprites draw them wherever scale them [19:36] rotate them but we're not really [19:38] interested in trying to compete with [19:39] openg if you need more power than that [19:42] you should probably be using openg [19:43] directly but if all you want to do is [19:45] knock out a Super Mario clone or a very [19:47] simple prototype or actually a really [19:50] good highlevel professional game that [19:52] just doesn't have really demanding [19:53] Graphics this is an API that you're [19:55] really going to want to look at uh and [19:56] I'll show you why momentarily uh it [19:58] handles I I call them Sprites on this [20:00] slide but literally it's just textur [20:01] sitting in GPU memory that you can just [20:03] Blitz the screen very quickly uh it can [20:05] do very simple blending Alpha blending [20:07] it can do Primitives like you know draw [20:09] a rectangle or a line uh it could scale [20:11] and rotate your textures and it can do [20:13] very basic color mods on them so uh you [20:16] can write simple games fast with it and [20:17] more importantly you can make Legacy [20:19] games amazing everyone works for a [20:21] company well some of you work for a [20:22] company that in the 1990s shipped a [20:25] really awesome 2D game when that was [20:27] like you know direct draw was new and [20:28] stuff like that I would love to see [20:30] those games on Steam I would love to see [20:31] those games updated and this is a really [20:33] good way to get that [20:34] game off of a software take your [20:36] software renderer and push it to the GPU [20:39] get steam overlay for that game get [20:41] scaling for Modern Hardware so you're [20:43] not playing in a little postage temp [20:44] window you can do a lot of amazing [20:46] things with it if you have a legacy game [20:48] so this is definitely something you [20:49] should be looking at if you have [20:50] something like I don't know Duke Nukem [20:52] 3D or something like that um and if you [20:55] need more power than this you should use [20:56] open gel but I want to give you a very [20:58] brief example here this is a there's a [20:59] game called dungeons of dread has anyone [21:01] played [21:02] this sorry [21:04] Nicholas uh the the guy who wrote it is [21:07] here um it's a really great Rog likee [21:09] game it's got 2D Graphics here's what it [21:11] looks like on Mac OS oh sorry about my [21:13] desktop it's messy what can I say [21:15] um uh it's Rog likee but you you'll note [21:18] it's basically 2D Sprites more or less [21:20] moving around they manage that and they [21:21] draw them and this used to be a 2d game [21:24] that just wrote directly to a frame [21:25] buffer and we moved it over to sdl2 as [21:27] an experiment and now it does all these [21:29] Sprites are in textures they're all [21:30] running on the GPU fixing a major [21:32] problem that they had with their Windows [21:33] people where the steam overlay will not [21:35] work if you don't use either openg G or [21:37] direct 3D but now once we push this to [21:39] steam the windows version using sdl2 [21:41] will suddenly have a steam overlay that [21:42] works which is fantastic um and that [21:45] that's the Mac version using sdl2 it [21:47] looks like the existing software [21:49] rendered version so it's not very [21:50] exciting but once we had this we said [21:51] you know sdl's incredibly portable and [21:55] now we can take advantage of gpus so [21:56] even on slower devices you don't have to [21:58] Software render this stuff to do alpha [22:00] blending Blitz and stuff like that so I [22:01] wonder what it would take to get running [22:02] on iPad so we did Total Lines of code [22:06] changed for this zero I mean we had to [22:08] pour it to sdl2 to be fair but once it [22:11] was an sdl2 thing this and this are the [22:14] exact same code and then we thought [22:16] could we take it further oh look there [22:18] it is on our Raspberry Pi zero lines of [22:21] code change um you we didn't get it [22:23] working on that Dreamcast at the bottom [22:25] yet but what can you do um but yeah [22:27] that's a Raspberry Pi hooked up up to my [22:28] television as a disclaimer gas lamps [22:30] game asked me to tell you that they are [22:32] not actually shipping this you know [22:34] maybe they'll experiment with it but we [22:35] just did this for fun to see if we could [22:36] do it don't start knocking on their door [22:38] for the Raspberry Pi Port um okay so but [22:41] the the gist is if you have a simpler [22:43] game that has simpler graphics and you [22:44] can move to the 2D rendering API that's [22:47] all you have to do and also this is [22:48] worth noting too touch events on an iOS [22:52] by default will look like Mouse clicks [22:53] if you don't care to look specifically [22:55] for touch events so this worked with the [22:57] regular Mouse input it thought it was [22:58] talking to a mouse it was actually me [23:00] tapping on the screen um okay disclaimer [23:03] good so if you want to use openg instead [23:05] so you can get more power this is [23:06] roughly what it looks like I lied there [23:07] are code samples in this I'm really [23:09] sorry about that [23:11] um if you get to uh okay so so you [23:14] create your window like we showed you [23:15] before and then you call GL create [23:16] context and say I need a GL context in [23:18] this window and then you're done period [23:21] you can uh see if that failed there's no [23:23] error checking here either I'm sorry I'm [23:25] a hypocrite all the way to the end um [23:27] and then when you're you make your open [23:29] jail calls you draw and when you want to [23:30] swap buffers you want to get that thing [23:31] to the screen you call sdlg swap window [23:34] and then your open jail renderings on [23:35] the screen period done um I just [23:37] minimized how easy it is to use open gel [23:39] right but but as far as like managing [23:42] open G and the context management that's [23:44] pretty much all there is to it uh and [23:45] you can do more complicated things you [23:47] can create multiple contexts and share [23:48] contexts and question so a number of you [23:51] probably went to be [24:04] yeah as Sam pointed out I just minimized [24:06] that anything you can do with open jail [24:08] you can do where that comment is I you [24:10] can get to incredibly complex stuff you [24:12] can write crisis 12 right there you can [24:14] write Unreal Engine 14 um you can do [24:17] anything is all of open jail is [24:18] available to you here at this point and [24:20] sdl will give you gives you very simple [24:22] ways to say hey is this open jail [24:23] extension supported um I don't have a [24:26] slide for that but it's literally one [24:27] function call I'm looking for this name [24:29] here's the string of it is this a [24:30] supported function it'll say yes or no [24:32] and then you know if you can call you [24:33] know the super new Shader Model 25 or [24:36] something like that um so I don't mean [24:38] to minimize it that's actually really [24:39] really important um you can do [24:41] incredible things and between those two [24:44] the create context in the swap window [24:45] where that comment is all of Team [24:47] Fortress 2 renders all of you know uh [24:50] hell painkiller hell and Damnation [24:52] renders Etc you know Sirius Sam 3 [24:54] renders there [24:56] um let's talk about events very quickly [24:59] here um these are what you'd expect from [25:01] any game that you might make you know [25:02] input from the mouse input from the [25:04] keyboard input from the window [25:07] um input from the window such as hey the [25:09] user just resized this you can stop it [25:11] from laying them resize it too don't get [25:13] nervous but you know all the things you [25:14] would expect from a basic windowing [25:16] system we fold it down into very simple [25:20] event Loops that looks something like [25:21] this hey give me the next event on the [25:23] event queue is it Mouse motion is it key [25:25] down did the user ask me to quit the [25:27] program Etc there's lots and lots of [25:29] events you can look for touch events and [25:30] window resizing and other things I'm not [25:33] even thinking of right now um but that's [25:35] basically all there is to it if you've [25:36] ever done a standard Windows Event Loop [25:38] it looks a lot like that but this event [25:40] Loop will work on every platform and [25:41] figure out what the event Windows Event [25:43] Loop looks like or what the Coco event [25:45] Loop looks like on Mac OS and your code [25:47] doesn't change one bit um we we try to [25:49] figure out how to make it look like [25:50] these abstract events um go back here [25:53] for one second um there's a touch API [25:55] like I said you can if you have an [25:57] Android uh device or an iOS device and [26:00] you want to poke at the screen we report [26:02] those uh by default we will have touch [26:04] events look like a mouse but the mouse [26:06] event will actually say hey this was [26:08] actually a finger um just so if you care [26:10] about touch events you know to avoid [26:11] those and if you don't you just do the [26:13] same Mouse code you did everywhere else [26:15] um you can do more complicated things [26:16] like that we can track multiple fingers [26:18] at the same time and we have a system in [26:19] there we call Dollar gestures so if you [26:21] can you can record very simple gestures [26:23] and sdl will tell you when the user has [26:25] made that magic set of swipes on the [26:27] screen [26:28] um as an event like hey he just did a [26:31] something symbol um joysticks and game [26:34] controllers we're going to talk about [26:35] all this in much more detail but if you [26:37] just want to know the guy wiggled his [26:39] stick he pushed a button you know that [26:41] like you can get that information and [26:43] then we have a higher level on top of [26:44] that that makes everything look like an [26:45] Xbox 360 controller don't get scared [26:47] that's actually a good feature yes um [26:50] does this include support for the steam [26:52] controller [26:55] to [26:56] API he he's asking if it supports the [26:59] steam controller and the answer is no [27:00] because the steam controller looks like [27:01] a mouse and keyboard so you have to use [27:03] Steam Works for that particular [27:04] controller um CU to the OS it doesn't [27:07] look like a joystick so did you have a [27:08] question [27:14] yeah I he asked if we support gamepads [27:18] on IOS and Android through this API and [27:20] the answer is I think do we we have [27:21] Android right now I think that just [27:22] landed uh we do not have IOS yet because [27:25] iOS 7 is the first thing that actually [27:26] had a formal API for joysticks and we [27:29] don't support like the Atari Cade thing [27:31] that was out before but that is going in [27:33] soon and it'll probably if we're really [27:35] lucky I'll get that written for the next [27:37] uh minor release and we'll just it'll [27:39] just magically work same code we'll just [27:41] support it on that platform uh but we do [27:43] not have that yet but it's easy to add [27:44] and it doesn't take any changes to your [27:46] code once we add it um uh okay and uh [27:49] timers you know you can set a timer and [27:51] say uh you [27:52] know I got questions hang on one second [27:55] um you can set a timer and say you know [27:57] fire an event every X millisecond so I [27:59] know to do something whatever and [28:01] that'll just come through as a special [28:02] timer event I have questions all over [28:03] the place hang on I think you were first [28:06] so let's go with [28:08] you [28:10] okay oh great and for the end [28:16] upb from the [28:19] okay [28:23] youp okay um well this is well he um [28:27] this this guy was one want people to [28:28] ship the new balers gate which is an [28:30] awesome game and you should all play it [28:31] if you haven't um he was saying that a [28:34] year ago they used sdl 2 which I'm going [28:35] to first off say a lot of developments [28:37] happened in the last year so things may [28:38] be better for this particular case but [28:40] the they get touch events from sdl but [28:42] for swiping events like you want to [28:43] pinch and stuff like that to like scroll [28:45] in they actually went directly to the OS [28:47] this is probably something worth noting [28:49] that I showed you dungeons of dread [28:50] running on iOS I and I'm up here like [28:53] zero lines of code changes but you will [28:55] probably want to do iOS specific things [28:57] now particular thing might be something [28:59] we can handle better if we're not we're [29:01] open to looking at that ofense oh yeah [29:06] well that he okay good good um part of [29:09] the reason they could do that and this [29:10] is part of the reason we changed the [29:11] license is uh it was hard to link lgpl [29:14] code in iOS and not violate somebody's [29:16] terms so the ZB license changed that [29:19] made that feasible for an iOS Port um [29:22] but you may want to even though you get [29:23] the game running on iOS you're still [29:24] going to want to give it iOS love [29:26] because people want to feel like an uh [29:28] an iPad app they don't want it to look [29:30] like you know uh a crappy port and [29:32] that's true if you're going from Windows [29:34] to a console or vice versa everyone [29:35] hates it when a Windows game has a [29:37] little logo from like a PlayStation [29:39] controller so like you know you you are [29:41] going to have to consciously clean up [29:42] those things in your game and your [29:44] particular issue is something we might [29:46] be able to handle better but that's [29:47] worth noting that we make you portable [29:49] but you still need to give it your own [29:50] polish and make it a good program to run [29:53] in the first place um okay let's move [29:55] past events real quick here uh the [29:57] joystick API you you can handle as many [29:58] sticks as the operating system will [30:00] report to us so if your OS will handle [30:02] 16 Joy USB joysticks you can plug them [30:04] all in and we'll report them all to you [30:06] will let you know as they come and go so [30:07] if someone rage quits their game and [30:09] Yanks their controller out and goes home [30:11] sdl will let you know so you can do [30:13] something and if they walk I'm like yo I [30:14] want to play and plug in a controller [30:15] you can announce a new Challenger [30:16] approaches and stuff that's all really [30:18] great stuff uh you can either pull the [30:20] joystick say what does it look like [30:22] right now and just get like a basic [30:23] state dump like you would get from X [30:25] input uh that kind of thing just tell me [30:27] what it looks like right now or you can [30:29] say I want events when every time they [30:31] hit a button send it through the [30:32] standard event ceue that I showed you [30:33] before and however you choose to react [30:35] to that you have you can use either [30:37] option they both work really well and [30:39] I've used both on different games um you [30:41] can query for axes buttons hats and the [30:44] name of the joystick uh so you can [30:46] actually you know this is a Logitech [30:47] wingman 3D and you can actually get that [30:50] string from sdl um and it'll tell you [30:53] when things come and go now that's the [30:55] lowlevel API and anyone's ever dealt [30:57] with direct input knows that this is [30:59] kind of a hard API to use because there [31:01] are a million joysticks out there and [31:02] they all look different they all work a [31:04] little differently and it's a little [31:06] frustrating [31:07] um so this works but you spend a lot of [31:10] time trying to decide where buttons are [31:12] and whether it can work and have to put [31:13] up this configuration UI to let people [31:15] calibrate their joystick and it's it's a [31:17] mess and it's been a mess for many years [31:19] so uh of all the things that Microsoft [31:21] has done well and not done well the [31:23] xinput API was actually really useful as [31:26] a model to say hey every everything [31:28] looks like an Xbox 360 controller and [31:30] they promis that by making sure it only [31:31] works with Xbox 360 controllers but [31:36] um but that turned out and that seems [31:39] like a really awful like vendor [31:41] antagonistic practice but that actually [31:43] turned out to be really good for a [31:45] subset of games where you could say I [31:47] want this thing to look like an Xbox 360 [31:49] controller I wrote Super Mario I want to [31:50] know where left right up and down is and [31:52] jump um and lots of games said this is [31:54] great in xut that I can just guarantee [31:57] this controller will work the way I [31:58] expect so we built something similar but [32:00] we don't have that vendor lock in we [32:01] built something called the game [32:02] controller [32:04] API I don't know how to do emoticons in [32:06] parenthesis so that's either a frowny [32:09] face in a parenthesis or a fat dude with [32:11] you know sadness [32:14] um everyone wants an Xbox everything [32:16] wants an Xbox controller especially if [32:18] you're porting games from Windows and [32:19] you see this a lot in the AAA but you're [32:21] starting to see it also in Indie Games [32:22] everything wants an Xbox controller [32:23] because they wrote to X input and they [32:25] built their whole game around that input [32:27] model so we gave you that but we've done [32:30] we take it a bit further what we've done [32:31] is we've started collecting gam pads and [32:33] controllers and all the weird things you [32:34] can buy in like the street corner in New [32:36] York City that was made somewhere in [32:38] China by the lowest bidder and has no [32:40] actual discernable name uh but [32:42] fortunately it has a valid USB vendor ID [32:44] and product ID so we look at these we [32:46] look at the GU ID that is presented to [32:48] the operating system we say we know what [32:50] to do with that controller we know this [32:51] button's over here this button over here [32:54] you know the it has two trigger buttons [32:56] and then we make everything no matter [32:57] what looks like if we can we make it [32:59] look like an Xbox 360 controller so you [33:01] still say I want the X Y A and B buttons [33:03] and we figure out what the hell that [33:05] means um now that seems like did you [33:07] have a question [33:12] yeah us he asked if that handles adapter [33:15] controllers for like you have like a [33:16] Super Nintendo thing and a USB adapter [33:18] for it it can um now keep in mind if we [33:22] haven't seen this before the answer is [33:23] no until someone sends us the basic [33:25] information then it can but um now the [33:28] model we went for for this is literally [33:30] an Xbox controller trigger buttons uh [33:32] shoulder buttons two analog sticks [33:34] clickable that are clickable home start [33:36] back did I miss any buttons on and the [33:38] triangle and stuff so basically it will [33:40] look like like an Xbox controller um an [33:43] Xbox 360 controller I don't know what [33:46] the Xbox one looks like at this point [33:47] but I'm sure it's probably similar um uh [33:50] but as we see these things we collect up [33:53] a database we have the more common ones [33:55] like if you plug in a PlayStation 3 [33:56] controller it's just going to work we [33:58] know what to do with that cuz I mean [33:59] it's a very common piece of Hardware um [34:02] but what we found though is that there [34:04] are a million pieces of hardware and [34:06] we've never seen them before so we said [34:07] hey if only we could crowdsource this [34:09] through millions of steam users so if [34:12] you go into steam with your really weird [34:14] joystick and you go into Big Picture [34:16] Mode there's a way to configure your [34:17] joystick when you do that we take note [34:19] of it and we send that configuration to [34:21] valve now when we see enough of those we [34:22] know that's common it's not someone [34:24] trolling us right so at that point we [34:26] collect all these up and we can say okay [34:27] now we have a good set of defaults so [34:30] when you plug that joystick in if you've [34:32] never configured it steam can make a [34:33] good guess at what that joystick is and [34:35] try to configure it directly and it will [34:37] pass that information to sdl when you [34:39] launch the game um if it's not in there [34:41] you can do it yourself we can give you a [34:43] configuration program or you can just [34:44] configure it in Big Picture Mode and it [34:45] will just work for you uh there's an [34:47] environment variable if you want to add [34:49] stuff and there's a way we can you can [34:50] give it a config file and say Here's [34:51] just all this stuff configuring this I [34:53] don't have it up on the screen but it's [34:54] literally just a string a weird looking [34:56] string of like this is when you see [34:58] button one that means button X you know [35:00] and go from there um so that's actually [35:03] been really useful for that and it a lot [35:06] of joysticks that shouldn't just work [35:07] with this now work which is much better [35:10] than the xinput model where you can get [35:11] that Simplicity if all you want is [35:12] joysticks game controller game pad [35:14] Simplicity but you don't have to rely on [35:16] having an Xbox 360 controller now this [35:18] also works on Windows and on Windows [35:21] behind the scenes optionally we can use [35:23] x input so if you have an Xbox 360 [35:25] controller it will still do the right [35:27] thing [35:28] without you using xinput directly so [35:30] this is an incredibly powerful API and [35:31] we're really proud of it and you should [35:33] definitely take a look at this if you're [35:34] doing that sort of thing it's a little [35:36] less flexible than if you're doing the [35:37] direct input model of tell me what's on [35:39] this stick and I'll figure it out but it [35:40] works really well and it just works [35:43] simply Without You screwing with it very [35:44] well and it's only getting better over [35:46] time like for example as we find out [35:48] that weird supernes USB thing we'll add [35:50] it to the list and such like that okay [35:53] the haptic API haptic is either Latin or [35:55] Greek I can't remember what for force [35:56] feedback hang on a second [36:09] question uh you may be doing it wrong [36:11] talk to me after the show and we'll work [36:12] out bug it's it's probably a very simple [36:13] thing and I know what but we'll we'll [36:15] talk about that uh also I should [36:17] announce that there are actually bugs in [36:18] any piece of software so it might be our [36:19] fault we'll fix it um question how would [36:22] sdl handle controll buttons XO it it [36:26] does how does it handle has more [36:28] functionality or less actually for that [36:29] matter than Xbox One the answer is we [36:31] provide the functionality we do it [36:33] entirely by the configuration that you [36:34] give it so if you say this is X and you [36:35] don't have any trigger buttons then you [36:37] just won't ever get trigger button input [36:39] and that's the best we can do we can't [36:40] physically make buttons appear out of [36:42] nowhere if you have more you have to [36:43] pick the ones but like I said it's a [36:45] less flexible API if you're writing a FL [36:47] simulator you absolutely do not want to [36:48] use this but if you're writing you know [36:51] Super Mario Brothers or hell even pilot [36:53] Wings you know this is what you should [36:54] be using it would be much better okay [36:56] haptic uh force feedback I'm sorry [37:11] question [37:14] okay okay U well like I said there there [37:17] may be bugs and and it may also be there [37:19] are joysticks that will show up as [37:20] joysticks but not as Xbox stuff we we'll [37:23] talk about specific problems you're [37:24] having with the library afterwards let's [37:25] try to we're running out of time so [37:26] let's just keep this to questions for [37:27] now and I'll talk to anyone after this [37:29] if you want to talk about a problem [37:30] you're having specifically um it's it's [37:32] no problem we'll it's probably our fault [37:34] and we'll fix it um okay so force [37:36] feedback um supports controllers and [37:38] mice most people have gamepads that [37:40] vibrate like I said the X Xbox 360 thing [37:42] but there is actually standards on some [37:44] platforms for like magic Logitech mice [37:46] that will vibrate on command um and so [37:49] we do actually have an API that will [37:51] support either of those or one or the [37:53] other whichever you like you can do [37:54] complex effects with it we it can work [37:56] like the direct input model for force [37:58] feedback where you say you know do you [38:00] have sine wave support do you have [38:01] square or triangle and all that stuff [38:03] and we will report back with the [38:04] hardware supports and let you program [38:06] those things specifically or you can [38:07] just say I just want simple Rumble I [38:09] just want the thing to vibrate at this [38:11] intensity and you know let me know when [38:13] you're done uh and of course Left Right [38:15] which is what anyone's used X input is [38:17] used to you can control the left motor [38:18] and the right motor separately we [38:20] support that also uh and there's a fire [38:22] and forget model you say just vibrate [38:24] this thing for three millisecond or [38:26] 300,000 uh 3,000 Mill 3 seconds [38:30] and then just stop and don't even let me [38:32] know I don't really want to track this [38:33] and manage it just make the thing Rumble [38:35] for a little bit and get back to me and [38:37] just keep going and you don't block on [38:39] that you just tell it to do it and it [38:40] will continue to do it in the background [38:43] um that's pretty much all there is to [38:45] that it's actually not that hard at all [38:47] it's it's kind of fun because for a long [38:48] many years we didn't have that so I was [38:50] always stubbing out the first feedback [38:51] code in video games I was pouring to [38:53] Linux and now I can actually have these [38:54] things vibrate which is really great um [38:56] okay the audio API it's extremely [38:59] lowlevel the model you want to be [39:00] thinking of is a dma buffer from direct [39:02] sound um it might be too low level so [39:05] I'm going to just have the disclaimer at [39:06] the beginning of this slide you may not [39:08] want to use the audio API this is [39:10] targeted people that are writing their [39:11] own mixers or people that already have [39:13] you know have their own uh 3D [39:15] spatialization they've done all they [39:17] want to do is push raw pre-processed [39:19] premixed PCM uncompressed data to the [39:22] audio card this is what you use so we've [39:25] recommended to a lot of people that you [39:26] use this on the engine that you're [39:28] building but the game itself should not [39:30] be working at this level um it supports [39:32] at the moment mono stereo quad 5.1 we're [39:36] about to add 7.1 support uh 86 13bit [39:40] unsigned little big little Indian big [39:41] Indian integer and floating Point these [39:43] all work if the system supports these [39:47] whatever format you went for like if [39:49] you're on Mac OS Core Audio wants to use [39:51] floating point if you're on Wave out you [39:54] probably want to use integer because [39:55] you're probably using Windows 3.1 um and [39:58] all these things it you give it whatever [40:00] you want sdl will convert it on the Fly [40:02] and hand it to the uh the audio device [40:05] in the format it wants to be in uh it'll [40:07] resample it for you if it needs to it'll [40:09] just basically you give it what you you [40:11] can produce as a video game and we [40:13] figure out what to do with it um but [40:15] like and this works in a callback this [40:16] call back usually fires in a separate [40:18] thread that we've spun ourselves um on [40:21] really old systems in the last version [40:23] like Mac OS classic we literally ran [40:25] this call back in a hardware interrupt [40:26] which is a Terri terrifying thing to do [40:28] but um but this you'll get a call back [40:31] every time we need more audio data for [40:32] from you and you just keep pushing audio [40:34] data in that function and go back to [40:36] your game without it interrupting it um [40:39] but really it's incredibly low level [40:40] it's what I call a Relentless stream of [40:42] PCM if you don't want to work at that [40:44] level you should pick something higher [40:46] because you have to mix this you have to [40:47] spatialize it you have to manage [40:49] everything yourself there are higher [40:50] level tools that might be better like [40:52] open na is an example sdl mixer is built [40:54] on top of sdl but it'll handle like [40:56] here's an MP3 play it only on the left [40:58] speaker and then it'll convert that [41:00] it'll mix that the way that sdl wants it [41:01] to be and and there's other Solutions [41:03] like fod or mild sound system there [41:05] there's lots of good Solutions and [41:06] that's why we let you turn this off if [41:08] this is too low level for you you can do [41:09] powerful things with this but the great [41:12] responsibility comes with blah blah blah [41:15] okay I'm running out of time so we're [41:16] going to keep on moving here uh the [41:17] threading API STL create thread does [41:20] exactly what you think it would do it uh [41:22] spins off a thread and it figures out [41:24] how to do that on your platform create [41:25] thread on Windows or P thread create on [41:27] Linux or whatever you have available to [41:29] you um it does one thing that's very [41:32] interesting that most uh apis don't do [41:34] you give it a string with a name and we [41:36] try to figure out how to make that name [41:37] show up in your debugger which is really [41:39] nice when you have a 100 threads you can [41:40] be like oh there's the one I was looking [41:41] for um uh so in that case and you have [41:45] to do some really black magic on some [41:46] platforms to make that happen so we [41:48] figured that out for you um we offer all [41:50] the other Primitives you would expect to [41:51] have if you have threads mutexes [41:53] semaphor conditions and most importantly [41:55] Atomic operations because everyone 's [41:57] written uh uh you know compare and swap [42:00] code and been scary we offer those for [42:02] you we figure out how that works on your [42:03] platform if the system offers it if they [42:05] don't we can try to do it with OP codes [42:07] that are specific to uh your processor [42:09] and your compiler you call the exact [42:11] same sdl function no matter what um it's [42:13] really scary to try and do that stuff if [42:15] someone hasn't done it for you so um and [42:18] you end up with very platform specific [42:19] codes so here you would just call the [42:21] same sdl compare and swap pointer or [42:24] integer 32 or whatever um okay moving on [42:28] other apis um these are things I'm not [42:30] going to cover in great detail but I'll [42:32] try to talk to them talk about them for [42:33] a minute or two here shared libraries [42:35] everyone's got that if def in their [42:36] program if their crossplatform if they [42:38] need to load a dll where they call load [42:40] library on Windows then if if else Linux [42:43] DL open if else BOS if you're still [42:46] doing that something else Etc uh that's [42:50] something that's easy to write yourself [42:51] but we made it easier it's always the [42:52] same thing I want to open this Library [42:54] it figures out how to do it I want to [42:55] find this symbol in this Library it [42:56] gives you back a pointer or null if that [42:58] symbol can't be found um very simple [43:02] message boxes I mentioned before there [43:03] is no n obviously there's a native uh U [43:07] Windows uh message box function that's [43:09] easy to call but there's not an X11 [43:13] message box it's easy to call so if [43:14] you're on a platform that doesn't have [43:16] one we'll literally build a window and [43:17] make it look like a message box like [43:18] you'd expect it to so that you don't [43:20] have to do it um and it's nice for error [43:23] messages it's nice for whatever um [43:26] sometimes you just need to be like [43:27] everything's broken I'm about to report [43:28] this game I'm sorry um and that's what a [43:30] message box is for we can access the [43:32] clipboard you can get and set things [43:33] from it through sdl and we figure out [43:35] how that works on your platform uh we [43:36] have something called CIS WM which is [43:38] the the fail safe in the worst case you [43:40] can get a platform specific window [43:42] handle and some other things that might [43:44] be platform specific so you will have an [43:46] if def there but if you absolutely [43:47] positively have to get at the system [43:49] level we don't hide that from you you [43:51] can grab it through this interface so [43:52] that it you know if you need to do some [43:54] magic Windows call on your wi 32 call [43:57] you're handled to a window here you go [43:59] um CPU info whether you have certain [44:02] feature sets what kind of uh do we do [44:05] processor speed I think we report that [44:06] too uh you know things like does this [44:08] processor have SS does it have MMX does [44:11] it have altc if you still have a really [44:13] old Mac or something like that um [44:15] standard lib if you uh we have replaced [44:19] all the things you probably care about [44:20] in the standard C runtime to make sure [44:22] they work everywhere the same uh SN [44:25] printf does not exist in the visual [44:27] studio it might in the newer versions [44:28] maybe I'm lying to you but in older ones [44:30] it was never there and there was this [44:31] really dangerous s print F that you [44:33] should never ever use but SN prf works [44:36] great on Linux so what we ended up doing [44:38] is having this very simple wrapper that [44:40] uh not also like I said on Windows we [44:42] never link to the cun time at all we we [44:44] provide all that stuff ourselves [44:45] including Malo if you need to allocate [44:47] memory we do that ourselves so that we [44:49] don't have to worry about [44:50] incompatibilities with the cun time and [44:52] different cun times that you might be [44:53] linking against on Windows um but we we [44:57] provideed all those functions to you if [44:58] you need like a very simple like string [44:59] compare it's guaranteed to be there and [45:01] work reasonably consistently and uh if [45:04] you don't need them that's fine you can [45:05] still call string copy yourself uh [45:08] timers if you need to know how many [45:09] milliseconds have gone by there's get [45:11] ticks if you need performance counters [45:13] like you would get from query [45:14] performance counters on Windows we [45:16] provide that interface now do you have a [45:25] question um he asked if you can do go [45:27] right to the system allocator on with [45:29] sdl internally we don't have an [45:31] allocator call back sdl Malik will [45:33] always do what sdl Malik does and what [45:35] does it do on Windows do we have like [45:37] yell Malik in there or something Sam's [45:39] laughing so we'll figure it out but um [45:41] it's probably a complicated answer [45:44] um okay yeah but we we do okay we we [45:46] actually use the win 32 directly uh win [45:48] 32 API directly but we don't let you [45:50] override that but we only use it [45:52] obviously for our own stuff you're free [45:54] to use sdl Malik but you can also not [45:56] use it not the best answer maybe we'll [45:58] put that in 2.1 it's actually not a bad [46:00] idea um because we we should do that [46:03] honestly okay what else uh uh timers we [46:07] just talked about read white write Ops [46:09] is a very simple uh just interface over [46:12] file IO so you can if you need to get [46:14] stuff from different sources we use it [46:16] for our own stuff like if you want to [46:17] have if you want to read a wave file [46:19] into sdl for the audio layer then it [46:21] takes a read write Ops instead of a file [46:22] pointer and all it is is just a list of [46:24] function pointers so you can say this is [46:26] coming from a file or it's coming from [46:27] memory or it's coming down a network [46:29] pipe it just handles all that for you um [46:32] you have to supply your own [46:33] implementation but it gives you a nice [46:34] abstract interface and we use it [46:35] ourselves for some things in sdl um file [46:38] systems where do I read files from where [46:40] do I write them to uh you know where's [46:42] the game installed where should uh users [46:44] put their save games at uh people have [46:46] been very badly behaved with this on [46:48] Windows in the past and windows is [46:49] starting to enforce that and Linux has [46:51] always enforced that and Mac OS and [46:53] stuff like that so this just lets you [46:55] figure out no matter where the platform [46:56] it's s wants you to store stuff we can [46:58] find that for you and tell you where [46:59] your specific game should put stuff um [47:02] Power is literally am I on battery am I [47:04] plugged in how much time is left on my [47:07] charge in my battery Etc like that very [47:09] important on mobile very important on [47:11] your laptop uh not so important on the [47:13] desktop it just says there's no battery [47:15] um presumably uh asserts we have an [47:18] incredibly powerful assertion macro um [47:21] I'm not getting into all the details [47:23] there's a lot of magical things that if [47:24] you're just using assert Doh it's much [47:26] much better there's blog posts about it [47:28] um the Angels Sing and weep when we code [47:30] this thing and finally sdl main which is [47:32] a very simple C piece of C code which is [47:35] it implements win main so that you can [47:37] simply have if you want on Windows you [47:39] can just have the standard int main argc [47:42] argv you just do it the same thing on [47:44] every platform and we handle the [47:46] difference between what Windows wants [47:48] with win Main and what the rest of the [47:50] world once with main you don't have to [47:52] use that as an optional piece but it [47:54] might make it so that again zero lines [47:55] of code changes your existing code just [47:57] works on new platform that you don't [47:59] know much about uh in this case it would [48:01] be Windows uh and some other platforms [48:03] need that too but it's mostly an [48:05] optional thing [48:06] now the near future these are some [48:09] things that are coming up did I forget [48:10] to take anything out of here no uh none [48:12] of these are Promises of anything but uh [48:14] these are things we want to do sooner or [48:16] later and hopefully sooner uh multiple [48:18] mice we have the API for it we do not [48:20] have it hooked up in the back end yet [48:21] but we want to make it so like you can [48:23] do with joysticks you can have three [48:24] mice plugged in on your desk and have [48:26] each player use a different one we'll [48:27] differentiate between them uh it's not [48:29] hooked up yet for most platforms it will [48:31] be eventually audio capture and video [48:33] capture so you can read from a webcam or [48:34] read from a microphone and do [48:36] interesting things like that uh that'll [48:38] be a new API so in there 7.1 audio is [48:40] coming soon that just hasn't been hooked [48:42] up you don't need to change anything [48:43] about your code except that you can then [48:45] use it if you want to by changing just [48:46] some values when you open the audio [48:48] device uh Wayland support is actually [48:51] already in Mercurial it hasn't shipped [48:52] yet uh mirror is coming very very soon [48:55] I'm playing around with lib DRC is a fun [48:57] little side project so you can send your [48:59] video game to your Wii U gamepad and you [49:01] know sit there and play like Super Meat [49:02] Boy on the GamePad uh that's not going [49:05] to be something you want to ship a [49:06] project with but it's just kind of a fun [49:07] little experiment on the side uh we have [49:09] a Windows RT port and more importantly [49:11] we have compatibility with the windows [49:12] store waiting to be merged into sdl it's [49:14] not there yet but it's about to be and [49:16] then you can ship a Windows store app [49:17] and pass our certification um we have [49:20] something coming up called sdl1 12 [49:21] compat where we're going to take the sdl [49:24] 1.2 API the old API and have it talk to [49:26] L2 behind the scenes so you get all the [49:28] new features but you don't have to even [49:30] recompile your program uh that's going [49:32] to solve a lot of problems for a lot of [49:34] people and uh finally the dynamic API [49:36] which lets you statically link sdl and [49:38] we can still override it uh if new [49:39] features come up so you can if if [49:42] dynamically linking makes you nervous we [49:43] can still make everyone happy there and [49:45] finally your requests here so if you [49:47] have something you think should be added [49:48] to this that would make your experience [49:49] as a game developer better we're [49:51] interested in talking to you and we're [49:52] interested in fixing your bugs and [49:54] interested in improving this software [49:55] and continuing to support it and build [49:57] it out so if you have something we [49:58] definitely want to talk to you after [50:00] this talk and crazy ideas are sometimes [50:02] really good ideas so don't be afraid all [50:04] right and I think oh one last slide here [50:06] and then we're going to take questions [50:08] uh there won't be a test you don't have [50:10] to memorize these links but we have [50:11] mailing list we have web forms which are [50:13] hooked up to the mailing list so you can [50:14] use whatever you're comfortable with [50:15] they go back and forth uh we have a Wiki [50:17] with some really really good [50:18] documentation and explanation of [50:20] everything we have a bugzilla that we've [50:22] gone through over 2,000 bugs in and [50:23] we've killed most of them um and we we [50:26] checked that religiously we have a build [50:28] bot we build this thing on like 14 [50:30] different platforms for every single [50:31] commit we do to sdl uh so that if it [50:33] breaks on a platform we know immediately [50:35] and it nags us very loudly uh we take [50:37] crossplatform support very very [50:39] seriously and then finally everything [50:40] else you can find it on the standard www [50:42] website all right that's all folks if [50:45] you have questions I will take them now [50:46] for the next am I out of time I took [50:49] questions all along if you have [50:50] questions afterwards then please see me [50:52] I'll be in the audience um otherwise you [50:54] know feel free to hire me I'm for sale [50:57] uh this is where you can find the slides [50:58] that's my email address that's my [50:59] Twitter and that's my go+ if you're [51:01] still using Facebook man it's time to [51:02] reevaluate your life thank you very much [51:09] [Applause]