Mr Speaker

Canvas and Inputs aren’t friends

Here are some cursory notes on a peculiar issue involving plummeting frame-rates when drawing input elements in DIVs that overlap canvas elements in fullscreen web apps. That's the kind of market I'm targeting these days.

tl:dr; Please test your canvas-capable device with this test case in normal and full screen modes, and report back the results!

In a recent experiment/game, I started up maxing out the iPhone 3GS CPU - getting around 14 frames per second (well Schrodinger's cat would argue that without (the fantastic) Mr Doob's Stats.js it would probably be a few more). I figured I could add some features as plain-old HTML elements without smashing that figure too much - so added an overlaying DIV to display preferences.

Interestingly, when the menu was showing the FPS count would drop at least 50%. It was just a DIV being drawn over the canvas element - but I figured this must be a big no-no on the iPhone. Then, out of interest I removed the HTML input elements from the DIV (leaving just the text) and the FPS count shot right back up.

Hmmm. After whittling everything down to the bare essentials I came up with this small demo to test it out. If you let it run for a while it will cycle between drawing under, then next to the DOM element with inputs: on an iPhone 3Gs the FPS takes a big nose dive when it "underlaps" the DIV.

But. If you also click the top of the DIV (containing the select boxes), the input boxes will disappear and again the FPS will return to sane levels. I thought it must be some reflow issue - but if I replace the input elements with divs, spans, paragraphs etc it's fine. I haven't tested images.

Any theories? Let me know if you see the same behaviour on your device (what version and firmware etc), or if you know why this is so!

4 Comments

  1. I’ve got:
    iPhone 3GS, iOS4.3.1.
    Next to Div: 31 fps.
    Underlapping: 13 fps.
    Underlapping no inputs: 29/30 fps.

    Saturday, April 2, 2011 at 10:39 pm | Permalink
  2. My theory is that the canvas is using some sort of hardware acceleration. When there is DOM elementage obscuring part of it, that hardware acceleration is turned off and you’re let with plain old HTML drawing.

    Saturday, April 2, 2011 at 10:47 pm | Permalink
  3. Hmmm, yeah, that makes sense – but why only the input elements? What’s so special about them, hey?

    Saturday, April 2, 2011 at 10:56 pm | Permalink
  4. iPhone 3GS, iOS4.3.2.
    Next to Div: 31 fps.
    Underlapping: 12/13 fps.
    Underlapping no inputs: 30 fps.

    iPhone 4, iOS4.3.2.
    Next to Div: 30/32 fps.
    Underlapping: 19/22 fps.
    Underlapping no inputs: 31/34 fps.

    I’d say the reason is similar to why inputs used to sit above Flash in desktop browsers (no matter what the z-index): the browser calls upon the OS to draw the native input formats. I guess there is a massive drop when another process (not the browser) needs to use the GPU. It would be interesting to test the FPS when the inputs are behind the canvas.

    Tuesday, April 26, 2011 at 9:58 am | Permalink
Captcha! Please type 'radical' here: *
How did you find this thingo? *