Open Bug 1141310 Opened 11 years ago Updated 3 years ago

Canvas 2d at power-of-two width and height on Galaxy Tab 2 paints pixels in swizzled order, scrambling the image.

Categories

(Core :: Graphics: Canvas2D, defect)

ARM
Android
defect

Tracking

()

People

(Reporter: bugzilla, Unassigned)

References

()

Details

(Whiteboard: [gfx-noted])

Attachments

(1 file)

User Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:36.0) Gecko/20100101 Firefox/36.0 Build ID: 20150224134236 Steps to reproduce: I was following the emscripten tutorial here: https://kripken.github.io/emscripten-site/docs/getting_started/Tutorial.html The SDL example creates a 256x256 canvas, and writes data to it one 32-bit value at a time, to produce a pleasant rainbow-like effect. I have experimented with other sizes of canvas, and other patterns including single pixel plotting, and the behavior is the same (though the results aren't identical, they are equally bad). It appears only when both the width and height are powers of two greater than or equal to 128, but lesser than or equal to 2048 (so: 128, 256, 512, 1024, or 2048). The canvas doesn't have to be square. So the issue appears at 256x256 (of course), and 128x2048, but not at 64x256, 4096x128, or 255x256, which all produce correct behavior. I have only tested this on the Samsung Galaxy Tab 2 7.0 (the system and firefox are both fully updated, according to the system), so it might be hardware or driver issue of this system. The issue does not appear on Chrome on the same device, Safari on my iPod, or my desktop Firefox. Interestingly, the thumbnail in "TOP SITES" always shows the canvas rendered correctly, so it's apparently re-rendering it and skipping some bugged shortcut. I've dug into the generated HTML and Javascript, and found no way to make it behave properly except by changing the canvas size. I'm not really a Javascript guy, so I haven't tried other ways of painting stuff to the canvas than putImageData. Actual results: The image in the canvas is scrambled. I believe, but am not certain, that pixels of the correct colors are being written in the wrong places. I'm uncertain of whether this causes the pixel data to be written to other locations of memory, potentially enabling exploits, so I've flagged this as a security issue just in case. Expected results: A smooth gradient of colors in the canvas, or otherwise correct pixel placement, as happens in every other browser and in this one whenever the canvas size is not 256x256 or other combination of powers of two.
OS: Linux → Android
Hardware: x86_64 → ARM
Not a security bug.
Group: core-security
hello.html and hello.js demonstrate the bug. hellosdl.cpp is the latest version of my source code (modified from the original tutorial to make it easier to try different canvas sizes) and compile.sh is the script I used to generate the html and js file from it.
The URL I've added is the same hello.html and hello.js that are in the zip attachment, so you should be able to reproduce the issue simply by visiting it with a system that can be affected by the bug: http://lrnj.com/powerof2/hello.html I've also uploaded a modified version that reduces the canvas size to 255x256, so it should work properly: http://lrnj.com/powerof2/hello2.html I've confirmed that the issue is present in hello.html (256x256, scrambled bands of color) and not in hello2.html (255x256, smooth color transition), on my Samsung Galaxy Tab 2 7.0. The behavior is correct (smooth color transition) at both URLs on desktop Firefox, Android Chrome, and iOS Safari. I'd appreciate if someone could test this with any other Android device, since I've only got my Tab 2 here.
I've now confirmed that putImageData isn't the only function affected: http://lrnj.com/powerof2/hello3.html This keeps the 256x256 canvas and simply replaces the putImageData call with a fillRect(25,25,100,100), which comes out weirdly scattered on Android Firefox (at least on the Tab 2). After experimenting some more, I'm pretty sure now that the pixels are being swizzled in a Z-order / morton code, then displayed in raster order, or vice-versa. Power-of-two pixel blocks are continguous in memory. (I would probably have guessed as much if I knew what "swizzling" was before I submitted this bug)
Summary: Canvas behaves abnormally at power-of-two sizes, scrambling putImageData pixels. → Canvas at power-of-two width and height paints pixels in swizzled order, scrambling the image.
Component: Graphics, Panning and Zooming → ImageLib
Product: Firefox for Android → Core
Version: Firefox 36 → unspecified
Please move to appropriate component if this is not correct.
Component: ImageLib → Canvas: 2D
I've made a much cleaner example at: http://lrnj.com/powerof2/hi.html Here is all the relevant code to reproduce the bug: <canvas id="canvas"></canvas> <script> var canvas=document.getElementById('canvas'); canvas.width=256; canvas.height=256; var ctx=canvas.getContext('2d'); ctx.fillRect(25,25,100,100); </script>
Okay, this seems specific to the Samsung Galaxy Tab 2, or at least only a small group of devices: https://twitter.com/ProjectLRNJ/status/575512225722593280 Three other users tried it with different devices and did not see the bug. Furthermore, it doesn't cause problems with non-visible canvases being used for webGL textures. http://delphic.me.uk/webgltext.html In this demo, if you have it directly display the 256x256 texture canvas on the page, it will come out swizzled (on the Tab 2), but it renders correctly in the webGL output canvas. This is probably why the bug (which I now assume is in a driver, not in Firefox) has gone unnoticed. I couldn't say whether the right thing now is to close the bug, try to get the driver bug fixed, or put a workaround in Firefox so it behaves correctly with the driver bug. Remember that the "TOP SITES" thumbnail renders correctly on affected systems, so the code to get it right despite the driver bug already exists in Firefox. But at this point, I've pretty much lost interest in pursuing it any farther myself.
Summary: Canvas at power-of-two width and height paints pixels in swizzled order, scrambling the image. → Canvas 2d at power-of-two width and height on Galaxy Tab 2 paints pixels in swizzled order, scrambling the image.
Whiteboard: [gfx-noted]
I can confirm that the Galaxy Tab 2 running Android 3.0 is affected. The canvas renders green instead of black. I have not run into any other devices that have this issue. Getting the vendor to fix the driver seems unlikely given that Samsung has not provided modern Android updates for the device.
Status: UNCONFIRMED → NEW
Ever confirmed: true
Severity: normal → S3
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: