linux as a gaming platform, ideology aside
DESCRIPTION
Linux commonly connotes with open-source zealots and a small PC market share, not blockbuster video games. However, the arrival of Steam on the platform might change the outlook quite dramatically, and Linux support may soon become a must-have feature for your game. Setting the open-source ideology aside, this lecture is an overview of the technical challenges a game developer may face while porting their game to this platform, along with solutions.TRANSCRIPT
Linux as a gaming platformIdeology aside
Digital Dragons · 19-04-2013
Leszek [email protected]
www.thefarm51.com
2What is this talk about?
www.thefarm51.com
It's NOT about:● Free software● Ideology● Business
It is about:● Linux 101● Development● Deployment
2
3Who is this guy?
www.thefarm51.com
Cross-platform work(→ de facto – Linux)
● github.com/inequation● Toy projects, personal utilities,
university stuff● Games as well!
● AC-130● Crystal Space● idTech 3-based games● Painkiller Hell & Damnation
● Linux as preferred OS for 7+ years● Former open-source evangelist
● Not anymore – lost interest
3
4Who is this guy?
www.thefarm51.com4
WHAT IF I TOLD YOU
WE PREACHED FREE SOFTWARE
5Who is this guy?
www.thefarm51.com5
6
www.thefarm51.com
Linux 101
6
7OMG LINUX!!11
www.thefarm51.com7
8OMG LINUX!!11
www.thefarm51.com
Richard M. StallmanSource: http://commons.wikimedia.org/wiki/File:RMS_iGNUcius_techfest_iitb.JPG
8
9OMG LINUX!!11
www.thefarm51.com
“F**k you, NVIDIA!” - Linus TorvalsSource: http://www.youtube.com/watch?v=iYWzMvlj2RQ
9
10Kernel and the distros
www.thefarm51.com10
Linux distro(Ubuntu, Debian, Fedora...)
Linux distro(Ubuntu, Debian, Fedora...)
LinuxkernelLinuxkernel
Freesoftware
Freesoftware
Proprietarysoftware
Proprietarysoftware
27+ supported CPU architectures!http://en.wikipedia.org/wiki/List_of_Linux_supported_architectures
We usually mean i386/amd64
11Who and why uses Linux?
www.thefarm51.com11
Who:● Scientists (TOP500)● IT companies● Hackers and
power users
Why:● It's free (well, duh...)
● It's robust● It's customizable
● Long, intrinsic traditions of free software● No established channels of proprietary
software distribution● But Steam can become a gamechanger!
12Standards
www.thefarm51.com
● Linux adheres to ISO/IEC standards, such as POSIX and Single Unix Specification...● System API – file system access, threading,
access control, IPC etc.● Command-line shell utilities
● ...which also happen to be supported by MacOS X, Android, iOS (yes, really!) and a handful of other OSes
12
13Standards
www.thefarm51.com
● Linux has OpenGL (ES) for 3D graphics rendering
● Linux has OpenAL for 3D audio with DSP● Linux has BSD sockets for networking● Linux has lots of other portable libraries● And all of these things are also available
on other platforms – Android, MacOS X, iOS, Windows!
13
14What does that mean?
www.thefarm51.com14
MacOS X
Linux Mobile*
* not to scale; actual overlap is greater
15There are issues, too
www.thefarm51.com
● Open source legacy → unstable ABIs● Why need a stable one when you can just
recompile the source?● This is why NVIDIA distributes glue code with
their drivers● Extreme heterogeneity
● Package managers (software distribution mechanisms)
● Patches applied to upstream code → potential differences in functionality
● Highly customized system configurations
15
16There are issues, too
www.thefarm51.com
● Proprietary vs free GPU drivers● Rule of thumb: free drivers perform more
poorly than proprietary ones● Intel only has free, but the hardware is bad anyway ☺● Legacy AMD/ATI GPUs only have free, and it's quite
good actually● NVIDIA drivers are equally good as the
Windows ones● AMD/ATI drivers are a bit worse than the
Windows ones ☹
16
17Solution?
www.thefarm51.com17
Assume Ubuntu.● For development and testing alike● Probably the most popular desktop
distro*● This is what Valve does- Bonus points: Steam compatiblity!
● Power users will get your game running on others anyway
* there are claims it's Linux Mint now, but it's still based on Ubuntu
18
www.thefarm51.com
Development
18
19Getting started
www.thefarm51.com
● Virtual machine● Fair enough for building● No such luck with testing
(unless you can virtualise your GPU)● Native installation
● Painless dual boot● Which disc image to download?
● Get whatever Valve recommends for Steam
(the Most recent LTS release is a good bet)
19
20Tools
www.thefarm51.com
● Tons and tons of IDEs, mostly average- Code::Blocks, Codelite are OK- There's also Eclipse if you can stand it
● Tried & tested native code toolchains- GCC, LLVM (clang)- gold – the new multithreaded linker by Google- GNU binutils – objcopy, objdump etc.
● VM toolchains- Mono, OpenJDK/Oracle JDK
● Build tools- GNU make, Cmake, SCons, GNU autotools
20
21Debugging
www.thefarm51.com
CPU● Classic command-
line gdb, gdbserver● Tons of front-ends- cgdb (command-line)- Nemiver, DDD (GUI)
Graphics● gDEBugger/CodeXL● NVIDIA Nsight for
Eclipse● apitrace
21
22SDL – the cross-platform “DirectX”
www.thefarm51.com
● Provides:- API in C with mappings to other languages- Timers and threads- Input – mouse, keyboard, joysticks/pads (incl.
Unicode characters)- Window management (incl. GL context)- Audio (very barebone)- 2D graphics (hardware blitting)
● Be sure to use 2.0 for new projects!- Support for OpenGL 3+- Support for multi-viewport apps
22
23SDL – the cross-platform “DirectX”
www.thefarm51.com
● SDL hides away most platform-specific code- That's right, no need to even use POSIX!
23
int main (int argc, char *argv[]) { // initialize SDL if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) < 0) return 1;
// set window caption SDL_WM_SetCaption("My SDL Game", "MySDLGame");
// hide mouse, grab input SDL_ShowCursor(0); SDL_WM_GrabInput(SDL_GRAB_ON);
// make SDL clean up on exit atexit(SDL_Quit);
// main game loop while (1) { // dispatch events while (SDL_PollEvent(&ev)){ switch (event.type) { // ... } } }
SDL_ShowCursor(1); SDL_WM_GrabInput(SDL_GRAB_OFF); return 0;}
24What if SDL doesn't cut it?
www.thefarm51.com
Despite its awesomeness, SDL has its shortcomings● No explicit GLX/WGL context data sharing
and no direct context access→ no threaded rendering ☹
(hit this corner while porting Painkiller HD)● No 3D positioning or DSP support in the
stock SDL audio subsystem- Partially remedied by SDL_mixer
But we need those! Now what?!24
25Just DIY – POSIX API
www.thefarm51.com
● Most WinAPI features map to POSIX- Threading (pthreads)- Advanced file I/O, incl. memory-mapped- Advanced memory allocation, incl. paging- IP sockets
25
#if defined(WIN32) || defined(__WIN32__) Emitter->InternalPtr = VirtualAlloc(NULL, Size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); // ...#else // It's a UNIX system! I know this! Emitter->InternalPtr = mmap(NULL, Size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); // ...#endif
26POSIX API
www.thefarm51.com
There is an extensive, centralised reference manual in the manpages-dev package● Type in a shell to access:
man <section number> <subject> ● Section number cheat sheet
1. General console commands2. System calls3. C standard library calls4. Special files (/dev/*) and drivers5. File formats and conventions
26
27X11 client API
www.thefarm51.com
● Windows graphical mode maps to X11- Xlib is a popular client library for the X(11) Window
System server- XCB is a more modern replacement (often a back-
end for Xlib)- Raw event pump, window management- OpenGL interoperability via the GLX extension
27
// event loopXEvent Event;while (XPending(GX11Display)) { XNextEvent(GX11Display, &Event); switch (Event.type) { // ... }}
28Joystick/gamepad API
www.thefarm51.com
● Not part of X11 input event framework● Kernel block devices- Created as /dev/input/js*-Hotplug events via libudev (also in Steam
Linux Runtime)-Handled via open() and ioctl()-Detailed documentation in the kernel
http://kernel.org/doc/Documentation/input/joystick-api.txt
28
29Porting a D3D renderer to OpenGL
www.thefarm51.com29
30Porting a D3D renderer to OpenGL
www.thefarm51.com30
Porting Source To Linux: Valve's Lessons LearnedValve & NVIDIA, GTC 2013
Video: http://goo.gl/jMX9ASlides: http://goo.gl/FtA5k
31How to deal with heterogeneity?
www.thefarm51.com
● As mentioned earlier, library ABIs tend to be unstable- Glibc tags its symbols with version → multiple
versions for backwards compatibility- Compile with newest version → binary might not
run on older versions● The ELF format is constant; but even then:- Dynamic libraries' “sonames” (including version
numbers) are baked in at link time → binary might not run if system provides a different version
31
32How to deal with heterogeneity?
www.thefarm51.com32
How?
Static linking+ will work forever- binary bloat
Distribute with libs+ will work forever- redundant to other games (also a form of bloat)- potential licensing issues
33How to deal with heterogeneity?
www.thefarm51.com33
Or use the Steam Linux Runtimehttps://github.com/ValveSoftware/steam-runtime
● Collection of essential packages “ripped” from Ubuntu repos + patches- freetype, glew, gtk+2.0, libgsm, libogg, libopenal1, libsdl1.2,
libsdl2, libvorbis, libtheora, libx11, libxcb, pulseaudio...- Release and debug versions of all libs
● Ready-to-use GCC-based toolchains for i386 and amd64
● Ships with Steam, so every (non-orthodox) Linux gamer has it
34Steam Runtime for non-Steam games
www.thefarm51.com
● Start-up shell scripts are common practice- Search for an installed Steam Runtime
instance- If not found, install your private copy-Only when the SLR is available, run the
actual binary
34
35Steam Runtime for non-Steam games
www.thefarm51.com35
#!/bin/shif [ -z $STEAM_RUNTIME ]; then STEAM_RUNTIME=$HOME/.steam/steam/ubuntu12_32/steam-runtimefi
if [ ! -d $STEAM_RUNTIME ]; then # install private copy of Steam Runtimefi
export LD_LIBRARY_PATH="$STEAM_RUNTIME/i386/lib/i386-linux-gnu:"\ "$STEAM_RUNTIME/i386/lib:"\ "$STEAM_RUNTIME/i386/usr/lib/i386-linux-gnu:"\ "$STEAM_RUNTIME/i386/usr/lib:"\ "$STEAM_RUNTIME/amd64/lib/x86_64-linux-gnu:"\ "$STEAM_RUNTIME/amd64/lib:"\ "$STEAM_RUNTIME/amd64/usr/lib/x86_64-linux-gnu:"\ "$STEAM_RUNTIME/amd64/usr/lib:"\ "$LD_LIBRARY_PATH"
# launch the actual game here
36Locales
www.thefarm51.com
● The C standard defines locales for language and regional settings (see man setlocale)
● They affect *printf()/*scanf() and more● Xlib can modify locale categories for GUI
apps (see man XSetLocaleModifiers)● Example POSIX locales: pl_PL.UTF8, en_GB.ISO-8859-1, ru_RU.KOI8-R
● The Linux manual might make it seem like retrieving current locale is as easy as calling char *locale = setlocale(LC_ALL, NULL);
36
37Locales
www.thefarm51.com
No such luck!// backup the original application localechar *Locale = setlocale(LC_ALL, NULL);char *OriginalLocale = NULL;if (Locale && *Locale) OriginalLocale = strdup(Locale);
// reset locale to system (user) defaultsetlocale(LC_ALL, "");// retrieve the default localeLocale = setlocale(LC_ALL, NULL);
// process locale here
// restore original localeif (OriginalLocale){ setlocale(LC_ALL, OrigLocale); free(OriginalLocale);}
37
38Extracting debugging symbols
www.thefarm51.com
● We often want to keep symbols for shipping binaries
● On Windows – keep the .pdb files● On Linux
objcopy --only-keep-debug \ "${tostripfile}" \ "${debugdir}/${debugfile}"strip --strip-debug --strip-unneeded \ "${tostripfile}"objcopy --add-gnu-debuglink= \ "${debugdir}/${debugfile}" \ "${tostripfile}"
38
39Crash handler
www.thefarm51.com
● On POSIX this is called a signal handler● Signals are a primitive IPC mechanism used
not only for crashes- Debugger traps, floating point exceptions, terminal
hangup, exit requests... See the output of kill -l● You can take a shortcut by using:- libSegFault – part of glibc, try:$ LD_PRELOAD=/lib/libSegFault.so \
/lib/libSegFault.so
- Andrew Tridgell's segv_handler http://www.samba.org/junkcode/#segv_handler
39
40A word on licensing
www.thefarm51.com
Whenever you use a library, check its licensing terms!● GPL is restrictive- Requires derivative works to use GPL
→ sharing the source code● LGPL is restrictive with linking exception-Allows linking to an LGPL library without
sharing the source code● MIT, BSD and Zlib licenses are generally
permissive, some might require advertising
40
41
www.thefarm51.com
Deployment
41
42Where do I put the files?
www.thefarm51.com
● Windows-Game data and binaries: C:\Program Files-User data: %APPDATA%, Documents...-AoS-like organization
● Linux (conventional)-Game binaries: /usr/bin/, /usr/games/-Game data: /usr/share/games/-User data: $HOME/.config/
($XDG_CONFIG_HOME environment variable)
- SoA-like organization- Filesystem Hierarchy Standard
42
43Where do I put the files?
www.thefarm51.com
● FHS mainly concerns distro packages● Proprietary software often installs into
/opt/<package name>/(“Add-on application software packages”)
● Proprietary software also often installs “wherever”
● Steam games live in ~/.steam/steam/SteamApps/
● Just put game data and binaries in one place, and save user data to ~/.config/
43
44Creating installation bundles
www.thefarm51.com
● Not relevant for Steam games (duh)● Simple .tar.gz archives
$ tar czvf <archive name> \ <input files...>
● Distro packages (.rpm, .deb...)● Self-extracting command-line installers as
shell scriptshttps://coderwall.com/p/y3upqw
● MojoSetuphttp://icculus.org/mojosetup/
44
45
www.thefarm51.com
Summary
45
46Summary
www.thefarm51.com
● Engineering costs of a Linux port for an already multiplatfrom game engine are low- “It's just an API”™
● SDL covers a lot of boilerplate for you● Overcoming heterogeneity is essential- Steam Linux Runtime is helping to fix it
● Watch out for those licenses!● When in doubt:-Use Ubuntu-Do whatever Valve does
46
48Special thanks
www.thefarm51.com
Ryan “Icculus” GordonInspiration & software contributions
Michał WielgusCritical review & free software comrade
Reinhard PolliceGetting stuff done for me on the PKHD port
48
49
Thank you!
Like us on Facebook!http://www.facebook.com/farm51http://www.facebook.com/deadfalladventureshttp://www.facebook.com/PainkillerGame
www.thefarm51.com