A couple of months back, Lunixbochs released a new port for the Pandora, Uplink – the original game from Introversion Software, a British indie developer (current working on Prison Architect, you may have seen it on Steam). The Uplink port was not a simple feat. This is a full featured PC game that was never made to run on mobile devices. While it may not look visually stunning, performance wise it proved to be challenging port, and Lunixbochs came with an interesting solution to the performance issue, by creating TinyGLES.
Our story starts back, way back. Lunixbochs had been working on this port of Uplink for a long while. But it just was not working as he expected.
Lunixbochs (LB): It only took me two and a half years, several betas, and two major projects to release a real version [of Uplink]. I was struggling with my port of Uplink to the Pandora. This story goes back as far as 2011. I originally ported Uplink when the source was released as part of the Humble Introversion Bundle. It had a huge codebase with rendering code spread all over, and I encountered many problems after my initial OpenGLES conversion. The text rendering did not translate well at all, so the text was blurry, badly offset, and unreadable. Images would disappear from the screen at random, and it was riddled with crashes. I think my patch to the game changed more than 3000 lines.
Lunixbochs is not the only one who went through this manual conversion of OpenGL code to OpenGLES. PtitSeb did also his share when he worked on the ports of Jedi Academy II and III for the Open Pandora. And both realized that this was probably not the best way to do porting. Lunixbochs took the first step to a better solution.
LB: Uplink is one of the main reasons I started working on glshim. I didn’t want to go through this again.
Since then, glshim has become an excellent porting solution for the OpenPandora. PtitSeb, one of the key porters on Pandora, has recently shared with me that most of his ports in 2014 were enabled heavily by glshim (even though Lunixbochs and him seem to keep separate versions of glshim in their dev branches). So this has become a pretty big deal. And this solved a number of problems for the earlier port of Uplink:
LB: Fast forward a couple of years. Now I have glshim, and I managed to get a completely unmodified version of Uplink working on it. This was pretty exciting, but there was one problem. It would either be unusable (less than a frame per second), or be kinda slow (5-20fps) but have no Z-order, which made overlapping elements break the game.
So, while glshim clearly made it possible to get the game working as expected, the performance gap was just too large to be usable on Pandora.
LB: Glshim was built with a single purpose: running OpenGL games on OpenGL ES drivers. OpenGL ES is a small subset of OpenGL, made to run on lighter hardware and be much easier to implement. This opened the space for me to write a fast OpenGL ES software renderer (which is a much easier undertaking) and get good desktop OpenGL coverage for free.
Luckily, the work did not really start from scratch, as the legendary Fabrice Bellard (of QEMU and FFMPEG fame) had created a similar library way back, showing that it was technically not a problem to create a software renderer for OpenGL.
LB: I found a project called TinyGL written by Fabrice Bellard a very long time ago. It was a simple software renderer for OpenGL, and initial tests showed it was actually pretty fast. I modernized the code and stripped away most of the parts glshim didn’t need. TinyGLES was born. TinyGLES supports: Drawing triangles, lines, points, and quads. Lighting, flat and smooth shading, texture mapping. Matrix math. That’s about it, but it’s enough for many games.
Actually glshim and TinyGLES work hand in hand. You have OpenGL code, glshim converts the OpenGL code to a GLES renderer. But instead of sending these GLES calls to the hardware renderer, you can send them to TinyGLES.
LB: glshim appears to the game as an OpenGL driver would. It does a lot of work to convert OpenGL calls into something a simple GL ES driver can handle. In this case, TinyGLES is the ES driver. TinyGLES takes the draw calls, rasterizes to an internal framebuffer with software, then draws it to the screen. Right now, that’s done directly using X11 APIs and something called SHM or Shared Memory. This greatly reduces overhead when drawing to the screen. In the future, I will probably add support for direct framebuffer output as well. I eventually want to merge TinyGLES with glshim, because there’s a lot of overlap. They both have huge chunks of code for things like matrix math and texture format conversion. Fun fact: glshim almost has enough code to render triangles itself. For GL_SELECT and GL_FEEDBACK, it has a raycast engine and can do all of the necessary transforms to place objects on the screen. My current plan is to add NEON support to the slow parts of the engine and hopefully achieve some great speedups on the Pandora.
You do not need to change any aspect of the original source code to make TinyGLES work.
LB: When I moved to TinyGLES, zero changes were required, because glshim considers it a real OpenGL ES driver.
So, how fast is TinyGLES, really? Did it really solve all the performance problems encountered with the first port?
LB: All of my benchmarks are through glshim, either with a TinyGLES backend or a real hardware OpenGL ES card. Performance depends very much on the device and resolution used. My primary “slow” development target here is the OpenPandora “CC” model. It’s an 800MHz ARM Cortex A8 with 256MB of RAM and a slow memory bus. If it runs well on the CC Pandora, it will run even better on everything else. The [previous] 32-bit renderer was too slow [in the original release], so I completely reworked the 16-bit rendering pipeline and optimized a ton of stuff (including NEON in some critical places), especially redundant memory copying. Uplink is now about twice as fast on my CC Pandora. It’s beating my original 1GHz numbers [which were at about 20-30 fps], and peaks at over 100fps.
On my 1Ghz Pandora, at 800×480 resolution, I get the following performance:
TinyGLES: 30-80fps, sitting around 50-60fps is pretty common.
TinyGLES: very, very glitchy graphics, but runs at 10-30fps
The biggest performance gain here is on Uplink, which is a 2D-heavy game and uses very crisp bitmap font rendering. This requires drawing directly to the framebuffer with glBitmap and glDrawPixels, which is not allowed in OpenGL ES. In TinyGLES, I can do whatever I want. The least expensive operation possible is drawing to the framebuffer, which accounts for the speed difference. It’s also worth noting TinyGLES is very close to hardware performance at many of the other games I’ve tried, and will only be getting faster in the future as it’s optimized.
In theory, TinyGLES could work about anywhere. But it seems like we are kind of lucky with the drivers and X11 interfaces on the Pandora.
LB: TinyGLES is nice on any system, because you don’t need support for OpenGL on your GPU. It could even work on the web with emscripten. Some OpenGL operations are simply slow or not supported in modern hardware and drivers, so it will probably always have a place: support for legacy software. The only thing that matters for TinyGLES is CPU and memory speed relative to screen size. I test it on my Intel laptop. It depends on X11, and it’s slowly getting NEON optimizations. It is significantly faster on the ARM A15 CPU than the provided Linux Vivante and Mali driver interfaces on my Samsung Chromebook and Cubox-i ARM computers. I’m sure the hardware chips are faster, but their drivers and X11 interfaces are so bad, TinyGLES ends up being faster by a large margin.
As you may have noticed, the Pandora port of Uplink is not just a port of the engine. It also includes all the assets needed to run the game. Basically you get the whole game for free. Lunixbochs was in touch with Introversions Software directly to make this port happen.
LB: I bugged them pretty often. I had it working long before I had permission. They eventually released the “Introversion Love Linux” blog post, which said “For instance If you show us a working Pandora version we’re not going to stop you launching, but we’ll need to have a conversation first.” I sent them a video via tweet and contact form, then they finally posted on the forums and responded to one of my emails.
This is what the original developers wrote in their blog post:
“We’ve had quite a few requests to be able to launch versions of Uplink onto other operating systems. We’ve had a chat about this and we are happy for standalone versions to be released (for free) on:
Always great to see the Pandora mentioned by big-profile developers! So… what’s next now, with TinyGLES ?
I was wondering if this Uplink port would lead to a potential port of Defcon. Which is another great strategy game by Introversion Software, albeit more 3D heavy.
LB: DEFCON was ported by slaeshjag around the same time, and he shared his progress with me. I’ve also ported it with glshim. It’s unfortunately not fast enough yet. Maybe it will work well with future versions of TinyGLES, as it’s mostly line drawing.
I guess we will have to be patient 🙂 Thanks to Lunixbochs for all his work to bring this port on the Pandora and for his time to answer my questions. Many thanks go to Introversion software as well for making a standalone release possible in the first place.