Investigating the possibility of an Android Mocha Doom branch.

I was currently investigating Android's raw bitmap rendering performance, to see if a Mocha Doom for Android branch would be feasible. Yeah I know someone already made a prBoom-derivative port for it, but good luck getting that closed-source binary blob to run on an unrooted phone, or getting it updated.

The good news is that the current Mocha Doom codebase is "digested" by the Android API, so if someone wanted to use the Mocha Doom logic to create a Doom-like game, it would be definitively possible, provided my "AWTDoom" app is replaced by one suitable for Android's system events.

Android's canvas drawing functions can be very fast, provided you use line, circle, filling etc. drawing primitives, and even pre-loaded bitmaps can be draw with scaling and clipping at a reasonable speed, even on pre-2.2 devices (hence, with no JIT). We're easily talking hundreds of updates per second, when using Canvas.drawxxx(...) functions.

As for max. screen update frequency, my Sony Xperia 8 (Android 2.1)is able to update a 320 x 400 pixel area more than 60 times per second, using a raw int[] array as a screen buffer and filling it manually each time using a modified arrayfill function, and that's without using OpenGL. If the array is already stored somewhere in memory (e.g. uncompressed animation), the time to draw it to screen is really negligible. These are the good news.

However, it goes downhill from here: Android doesn't support any form of indexed display, and even 16-bit bitmaps are treated as hicolor RGB and are forcibly blown to a full 32-bit Canvas before being drawn.

The problem is that Doom is a game that relies on indexed palette manipulation for its lighting and colormap tricks, and on the ability to set an arbitrary palette of colors for some of its visual effects, so if I keep the inner working intacts.

I benchmarked how long it takes for Android to copy the contents of an int[] array to another and then display that to the screen, and usining an optimized array fill operation resulted in a 60 fps update at 320x480 resolution. However, converting a byte[] array to an int[] one using a palette table (which is what a Doom source port will need to do at the end of each frame.some point) was SHIT SLOW. It doesn't help that there's no native function to do that, and no JIT in 2.1.

So slow in fact, that it can't be performed faster than 10-12 fps at vanilla resolution, at least on a JIT-less Android implementation (still stuck with 2.1, sigh). Even the existing mixed-code Doom for Android that uses a prBoom binary blob is quite slow to update, and I think that one actually uses a GL surface to force hardware palette conversion, which means creating a new GL texture each frame. Unsurprisingly, that one doesn't run very smooth either.

So, either I wait and see if 2.2 will definitively solve this bottleneck on the same hardware, if Google decides to add native support for indexed 8-bit or even 16-bit images (which is why Mocha Doom works so quickly on the desktop), or if there is a way to implement a 32-bit renderer without using colormaps. Another way would be to write a special primitive-based renderer for Doom e.g. draw sprites as clipped and scaled bitmaps, which are generally hardware accelerated even without using OpenGL. If this could be extended to textures too, it would make an awesome novel implementation of Doom's renderer (at least some pure 2D elements like the menus, automap and sprites could be def. drawn this way).

Share this post


Link to post

Nice investigative work.

Has there been any recent progression on the codebase proper? Is it any more or less playable at this point than the last public betas you went through with?

Share this post


Link to post
AlexMax said:

Has there been any recent progression on the codebase proper? Is it any more or less playable at this point than the last public betas you went through with?


The version currently in the CVS has some extra features like support for DEUTEX flats in PWADs, and definitive removal of the SSEGs limit, and also a fix that allows it to work on OS X, along with some overflow fixes, but it's not more playable, sorry. I have a priority to finish my MSc within March, so I will resume work on it after that date. At most I could release a 1.3 beta so that OS X users could try it too (works just like on Linux).

Share this post


Link to post

I have a Droid currently running Android 2.3.2 and I can downgrade to 2.2 for testing as well if you'd like to start making public alphas/betas/whatever :p

Share this post


Link to post

What if you created specialized versions of R_DrawColumn and R_DrawSpan that blow up the memory addresses to int[] and remap the colors while doing the original drawing pass, so that you end up with a pre-expanded framebuffer?

Seems like it should in theory be less expensive than doing the normal drawing and then converting the entire buffer to int.

Share this post


Link to post

I'm no expert on DOOM software renders but I would have thought that would indeed be quicker because you'd be able to write the three-value pre-computed BGR value set for a given palette index in one. Thus avoiding the potentially expensive 8 => 24-bit whole frame processing entirely.

The only potential drawback is repeated processing of a given pixel but as DOOM's software renderer already goes to some lengths to avoid overdraw - its probably not going to be an issue.

Good idea.

Share this post


Link to post

Wow, I had almost forgotten about this thread...in any case, the HiColor branch development is quite close to what Quasar has suggested: all drawing functions are specialized and write 16-bit (565 RGB) values directly to a screen buffer, while an expansion to 24-bit or 32-bit truecolour would be trivial. The "palettes" are actually extended COLORMAPs.

There's no frame post-processing required, so if I even move on and try this, it will be based off the HiColor branch, the very least.

Share this post


Link to post
Maes said:

but good luck getting that closed-source binary blob to run on an unrooted phone, or getting it updated.

My phone is unrooted and runs it fine. There're lots of apps using native code now; Firefox and VLC, for example.

Share this post


Link to post
tempun said:

My phone is unrooted and runs it fine. There're lots of apps using native code now; Firefox and VLC, for example.


That comment was made over a year ago, and now things have changed. The Android NDK itself can now target multiple CPU architectures (including MIPS and Intel) with a sort of "fat binary", but for older stuff, there was the implicit assumption that the underlying hardware would always be ARM-based, and I wondered whether this could break things in the future, eventually. We're also talking about older releases of the Android OS, and 2.1 was still king just about a year ago.

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now