Solving black screens and corrupted graphics in HTML5 games on the Samsung S3
One thing we always try to do as HTML5 game developers is maximise performance. This isn’t an easy task as pretty much every handset is fighting against you when it comes to draw speeds and available RAM in the browser. So when I ordered a Samsung Galaxy S III – quite literally the pinnacle of the Samsung device range at the moment, I wasn’t expecting its beast-like technical specifications to give me any problems at all. Oh how wrong I was.
For some reason several of our games were either turning entirely black or parts of them were not displaying at all. They didn’t crash, there was no error log entry to look at, they just didn’t actually display. The game was still running however, sounds could be heard and touch events were still received – so if you knew where to touch you could still play it, it just wasn’t rendering anything. What followed was a full day and sleepless night spent debugging to find the solution. It was such a task I had to share it here to help fellow devs!
Debugging without a debugger
After many hours of head-scratching I finally tracked down the issue to a setting in the Android browser. The S3 runs Android 4.0.4 Ice Cream Sandwich, so there is no sign of Chrome yet. Incidentally this problem doesn’t exist on my Nexus 7 running Jellybean, so it appears to be confined to ICS and/or the Samsung phones.
You’re probably thinking it was something trivial like “I bet his images weren’t sized to powers of 2” but if only the issue had been that simple. What it transpires to have been is that the browser can’t handle layered canvas objects when GPU acceleration is turned on. As I mentioned at the start we try to keep our games responsive, which isn’t always easy, but one way to do that is to make sure you keep screen re-draws to a minimum. So if we have a background scene to our games that doesn’t change very often we’ll render it to a canvas object and then layer the game foreground on-top of that, so we don’t have to waste time refreshing non-changing graphics every frame.
However it would appear that with OpenGL rendering enabled the S3 isn’t capable of compositing together two canvas layers if they are positioned over the top of each other via CSS.
When it can’t handle the rendering I’ve witnessed it do all of the following:
1) When it can’t render the canvas, for whatever reason, it hides it. It literally skips it when rendering the page, so it is still present in the DOM, still responds to touch events and the like, it just doesn’t visually appear.
2) Another anomaly I noticed was that sprite sheets and texture atlases no longer work. It’s incapable of grabbing a portion of an image when using the context.drawImage function. What happens is that the entire image is rendered, but shrunk down into the size specified in the drawImage call. So your entire sprite sheet appears.
3) Images appear stretched. Especially true for image sizes that don’t fit into ^ 2. The top left corner of the image is stretched down across the entire image size.
I’m not sure if these bugs are specific to the S3 or an Android 4.0.4 bug that may be present on other handsets too. It wasn’t just our games though, even GMail didn’t load properly and would black screen from time to time. Debugging this was a nightmare – google search turned up nothing, there was no handy StackOverflow answer waiting for me. Hence why I wrote this post!
How to solve it?
2) Don’t layer DOM objects that are hardware accelerated! I hit this problem with 2 canvas elements on-top of each other, but I dare say it could happen with other types too. Video on-top of canvas for example, or hardware accelerated CSS3 on-top of canvas. Ideally if I had time I would research exactly the combinations that fail, but I don’t right now – if you do, please share your results in the comments.
Performance of the S3 was excellent especially given how large its screen is. It ran our games wonderfully, once they were fixed 😉 If your game just uses a single canvas with nothing else then you’re probably going to be ok. If you’ve got some huge texture sizes, then maybe not. Also the phone by default has a Power Saving mode enabled, which appears to mean that it will look to see if the page is made-up of lots of DOM objects and if so slows down to a crawl when updating them. Maybe to preserve battery life? But I did notice that several DOM only games ran at around 2 frames per second. So that’s another thing to be aware of.
Screen Grabbing from Android
Just quickly I wanted to give a shout-out to the excellent free tool Android Screen Capture for Windows. It hooks into the Android SDK and Dalvik Debug Monitor and allows you to stream images direct from the handset to your PC, which can be very handy indeed! The hardest part was getting the Samsung registered as a device on Windows 7. For that the Google USB driver won’t suffice, you need to go to the Samsung support site, scroll to the bottom of the page and pick the “Manuals and Downloads” tab, then use the link for “Software” to see the USB driver. Once the S3 appears in Dalvik you’re good to go.
Posted on September 7th 2012 at 3:32 pm by Rich.
View more posts in HTML5. Follow responses via the RSS 2.0 feed.
7 ResponsesLeave a comment
Make yourself heard
All about Photon Storm and our
HTML5 game development services
Filter our Content
- Cool Links
- Flash Game Dev Tips
- Game Development
- Geek Shopping
- In the Media
- Phaser 3