Does GPU accelerated canvas rendering have any effect?

784 views
Skip to first unread message

Ben Harper

unread,
Feb 28, 2015, 6:48:17 AM2/28/15
to blin...@chromium.org
Hi,

I'm trying to understand how canvas is rendered, and specifically if path fills are rendered on the GPU.

The following things puzzle me, and I would appreciate any answers that help bring clarity to any of these questions.

1. Three years ago, code was committed to WebKit that did Blinn/Loop rendering of cubic splines via the GPU. This code doesn't seem to be in the Blink repo anymore. Was it ever used. If not, why not?
2. I have setup an example, linked to below, which seems to indicate a sub-pixel resolution of 1/4 pixels. Is this the Skia backend, and are there plans to improve on this quality?
3. I cannot see any difference when #disable-accelerated-2d-canvas is on or off. I also can't find code in the Blink repo that draws 2D canvas paths via the GPU. What does this setting actually control?

Here is a link to an example which demonstrates the antialiasing quality:


As you move the cursor in and out of pixel (1,1), you'll notice big jumps on the number at the bottom. You'll also notice those big jumps on the canvas image itself. An ideal system would give you 256 levels, even if you move the cursor only horizontally or only vertically.

Thanks,
Ben

PhistucK

unread,
Mar 2, 2015, 3:53:29 AM3/2/15
to Ben Harper, blink-dev
Are you sure it is accelerated by default on your system?
Check about:gpu to see if hardware acceleration for 2D canvas is enabled at all. Otherwise, you should not feel any difference.


PhistucK

To unsubscribe from this group and stop receiving emails from it, send an email to blink-dev+...@chromium.org.

Elliott Sprehn

unread,
Mar 2, 2015, 1:42:24 PM3/2/15
to Ben Harper, Justin Novosad, blink-dev
On Sat, Feb 28, 2015 at 3:48 AM, Ben Harper <rog...@gmail.com> wrote:
Hi,

I'm trying to understand how canvas is rendered, and specifically if path fills are rendered on the GPU.

The following things puzzle me, and I would appreciate any answers that help bring clarity to any of these questions.

1. Three years ago, code was committed to WebKit that did Blinn/Loop rendering of cubic splines via the GPU. This code doesn't seem to be in the Blink repo anymore. Was it ever used. If not, why not?

Skia does that stuff for us, so it's not in the blink repo.
 
2. I have setup an example, linked to below, which seems to indicate a sub-pixel resolution of 1/4 pixels. Is this the Skia backend, and are there plans to improve on this quality?
3. I cannot see any difference when #disable-accelerated-2d-canvas is on or off. I also can't find code in the Blink repo that draws 2D canvas paths via the GPU. What does this setting actually control?


junov@ is our canvas expert and can probably answer these. :)

Justin Novosad

unread,
Mar 2, 2015, 2:00:25 PM3/2/15
to Ben Harper, blink-dev
On Sat, Feb 28, 2015 at 6:48 AM, Ben Harper <rog...@gmail.com> wrote:
Hi,

I'm trying to understand how canvas is rendered, and specifically if path fills are rendered on the GPU.

The following things puzzle me, and I would appreciate any answers that help bring clarity to any of these questions.

1. Three years ago, code was committed to WebKit that did Blinn/Loop rendering of cubic splines via the GPU. This code doesn't seem to be in the Blink repo anymore. Was it ever used. If not, why not?

Path rasterization is entirely handled in skia. Skia does something similar, but we are currently missing an implementation for rendering anti-aliased concave paths on the GPU. In those cases, we end up rasterizing the path on the CPU, and uploading it as a texture to the GPU. senorblanco@ is working on making this better.
 
2. I have setup an example, linked to below, which seems to indicate a sub-pixel resolution of 1/4 pixels. Is this the Skia backend, and are there plans to improve on this quality?

@senorblanco?
 
3. I cannot see any difference when #disable-accelerated-2d-canvas is on or off. I also can't find code in the Blink repo that draws 2D canvas paths via the GPU. What does this setting actually control?

Possibly because the paths are being rendered on the CPU (antialiased + concave), or your GPU/driver is blacklisted for canvas acceleration (see chrome://gpu), or your canvas is small (below the 256x257 acceleration threshold).

Stephen White

unread,
Mar 2, 2015, 2:14:27 PM3/2/15
to Justin Novosad, Ben Harper, blink-dev
On Mon, Mar 2, 2015 at 2:00 PM, Justin Novosad <ju...@chromium.org> wrote:


On Sat, Feb 28, 2015 at 6:48 AM, Ben Harper <rog...@gmail.com> wrote:
Hi,

I'm trying to understand how canvas is rendered, and specifically if path fills are rendered on the GPU.

The following things puzzle me, and I would appreciate any answers that help bring clarity to any of these questions.

1. Three years ago, code was committed to WebKit that did Blinn/Loop rendering of cubic splines via the GPU. This code doesn't seem to be in the Blink repo anymore. Was it ever used. If not, why not?

Path rasterization is entirely handled in skia. Skia does something similar, but we are currently missing an implementation for rendering anti-aliased concave paths on the GPU. In those cases, we end up rasterizing the path on the CPU, and uploading it as a texture to the GPU. senorblanco@ is working on making this better.
 
2. I have setup an example, linked to below, which seems to indicate a sub-pixel resolution of 1/4 pixels. Is this the Skia backend, and are there plans to improve on this quality?

@senorblanco?

Skia's software path rasterizer uses a supersampled grid of 16 (4x4) samples. You'll see this in software path rendering (when accelerated canvas is blacklisted on your GPU, or the canvas size is below the acceleration threshold, as Justin notes) or in GPU-accelerated canvas when concave paths are drawn. We don't currently have any plans to do antialiasing above 16 samples, but of course we're always looking for new approaches that strike a good balance between quality and performance.

Stephen

Ben Harper

unread,
Mar 2, 2015, 3:22:30 PM3/2/15
to blin...@chromium.org
Thanks for all the feedback, much appreciated!

My GPU is not blacklisted, but my small canvas size was the problem. The path I'm drawing is convex.

I tried raising the canvas size to 260x260, and indeed the quality is much better. By moving the cursor in a specific way I can still produce some discreet jumps, but generally it looks like 1/256 precision.

So this raises another two questions from me:

1. Why is the threshold 256x257? Map tiles, especially "Canvas" tiles as rendered by Leaflet, are 256x256 pixels big, and the poor quality 4x4 sampling happens there. It would be great if our map layers that render themselves via HTML Canvas had better quality. Would you consider lowering this threshold, or suggesting another workaround?

2. Where is the code that does the GPU-based path rasterization?

Regards,
Ben

Florin Malita

unread,
Mar 3, 2015, 8:57:09 AM3/3/15
to Ben Harper, blink-dev
On Mon, Mar 2, 2015 at 3:22 PM, Ben Harper <rog...@gmail.com> wrote:
2. Where is the code that does the GPU-based path rasterization?


On Saturday, 28 February 2015 13:48:17 UTC+2, Ben Harper wrote:
Hi,

I'm trying to understand how canvas is rendered, and specifically if path fills are rendered on the GPU.

The following things puzzle me, and I would appreciate any answers that help bring clarity to any of these questions.

1. Three years ago, code was committed to WebKit that did Blinn/Loop rendering of cubic splines via the GPU. This code doesn't seem to be in the Blink repo anymore. Was it ever used. If not, why not?
2. I have setup an example, linked to below, which seems to indicate a sub-pixel resolution of 1/4 pixels. Is this the Skia backend, and are there plans to improve on this quality?
3. I cannot see any difference when #disable-accelerated-2d-canvas is on or off. I also can't find code in the Blink repo that draws 2D canvas paths via the GPU. What does this setting actually control?

Here is a link to an example which demonstrates the antialiasing quality:


As you move the cursor in and out of pixel (1,1), you'll notice big jumps on the number at the bottom. You'll also notice those big jumps on the canvas image itself. An ideal system would give you 256 levels, even if you move the cursor only horizontally or only vertically.

Thanks,
Ben

Justin Novosad

unread,
Mar 3, 2015, 11:25:07 AM3/3/15
to Ben Harper, blink-dev
On Mon, Mar 2, 2015 at 3:22 PM, Ben Harper <rog...@gmail.com> wrote:
Thanks for all the feedback, much appreciated!

My GPU is not blacklisted, but my small canvas size was the problem. The path I'm drawing is convex.

I tried raising the canvas size to 260x260, and indeed the quality is much better. By moving the cursor in a specific way I can still produce some discreet jumps, but generally it looks like 1/256 precision.

So this raises another two questions from me:

1. Why is the threshold 256x257? Map tiles, especially "Canvas" tiles as rendered by Leaflet, are 256x256 pixels big, and the poor quality 4x4 sampling happens there. It would be great if our map layers that render themselves via HTML Canvas had better quality. Would you consider lowering this threshold, or suggesting another workaround?

The 256x257 threshold meant to be a compromise. Generaly speaking, software-rendered canvas have slower rendering throughput but less overhead, so software rendering is preferable (from a performance stand point) for canvases that have a small number of pixels to fill because the performance gain of the GPU does not offset the cost of setting up and compositing a GPU-accelerated layer. That fixed cost of the GPU layer is well amortized on larger canvases.  That being said, the size of a canvas is not the most accurate heuristic for gauging the tradeoff, but it is a very predictable one. It's current value was chosen in particular to help the performance of sites that use Google maps APIs to display map overlays (using canvases) in 256x256 tiles, whiche general rendered faster in software.  This decision was taken without much consideration for rendering quality, we were mostly concerned about performance at the time. I don't think it ever occurred to any of us, that 16x multisampling would be considered limiting to content creators.

It should be noted that the canvas specification does not provide any controls for anti-aliasing. In fact, the spec does not even require anti-aliasing.  From a standardization perspective anti-aliasing is considered to be a "quality of implementation" issue that is at the browser implementor's descretion.  So if quality of anti-aliasing is absolutely critical for your application and you want your code to be portable, you should consider taking the issue into your own hands and stop relying on the the browser.  The web platform just doesn't provide the level of control you appear to be looking for. To do so, there are several things you can do:
* If the paths are static, you could pre-render them into images, and have your implementation just deal with images (I doubt this would work for your use case)
* You could render the paths interactively on the server side, using a canvas implementation that is under your control (node.js?)
* You could implement your own path rasterizer in JS and use putImageData to paint it to the canvas.
* You could render paths to a large offscreen canvas and downscale the results.  Because the exact behavior CRC2D.imageSmoothingEnabled=true depends on the combination of browser/OS/GPU/driver, you would probably want to implement your own down-sampler that operates on ImageData (much easier than writing your own path rasterizer). So it would go something like this: 1) draw path to offscreen canvas 2) getImageData 3) down size and filter the image data 4) paint to canvas with putImageData.

Ben Harper

unread,
Mar 4, 2015, 7:30:39 AM3/4/15
to blin...@chromium.org, rog...@gmail.com
Once again, thanks for the detailed response.

Creating an offscreen canvas works as you suggested.

To be honest, the 16x supersampling of the software path is probably good enough for our needs, and it will only become less important as screen resolutions climb.

Nevertheless, I'm very happy that I could get such detailed feedback on the internals.

Regards,
Ben
Reply all
Reply to author
Forward
0 new messages