Tuesday, July 24, 2012

Azure Canvas

Other than the mask layers stuff, most of my work has been on getting Azure canvas working, passing tests, and landed in the tree. Most of the work has been done before, my contribution has been on debugging, testing, and wiring things together, and of course a few interesting edge cases. To describe the work, I'll give a little background on our graphics libraries.

Back in the day, 'all' rendering in Firefox was done using the Cairo graphics library. This was wrapped in a thin wrapper library called Thebes (Cairo is the external library which does all the work, Thebes is the internal wrapper). We would like to support different graphics libraries and we would like a more efficient wrapper layer, and so was born Azure. This is a new internal system which abstracts a lot of our drawing code. Multiple backends can be slotted into Azure, and, in turn, Azure can be used as a backend for Thebes instead of using Cairo. So, for example, our graphics stack could use Thebes on top of Azure on top of Cairo (or Skia or Direct2D, etc.). Azure has some interesting advantages over Thebes, mainly that it is a state-less API (well, except for a transform and clipping rect), Bas and roc have written some interesting blog posts about this before.

The long term plan is for Thebes to be removed, and Azure to be used directly. For now there are people implementing content rendering using Thebes on top of Azure (on top of Direct2D on Windows, Core Graphics on Mac, and Skia or Cairo elsewhere).

HTML 5 canvas uses a different rendering path from the rest of content. We actually have two canvas implementations right now, one on top of Thebes and one on top of Azure. Currently the latter is used only on Windows where Direct2D is present, and the Thebes canvas is used elsewhere. We want to remove the Thebes canvas, because having two canvas implementations is a maintenance burden and affects our DOM bindings implementation.

So, I have been working on getting Azure canvas working with both Skia and Cairo backends, the former only on Windows, the latter everywhere, with Anthony Jones. It is all about ready to land, after that, we'll let it settle for a while to ensure there are no problems, and then we can remove Thebes canvas completely. Some of the interesting bits of this work have been using Skia canvases as source for tab previews on Windows, organising different backend preferences on different platforms, and ensuring we can always fall back to a safer backend, and just getting all the complex logic in Azure canvas and the various backends right. Plus the occasional memory leak, and some interesting interactions between the layers system and Azure.

In terms of the bigger picture, this work should lead to Azure totally replacing Thebes for canvas rendering. Elsewhere, Azure is being developed into the primary backend for Thebes, so that it will be used everywhere for rendering content, rather than using Cairo directly. Then we will work to remove the Thebes layer altogether so we are rendering directly with Azure, this will be fiddly because there is Thebes code everywhere in the code base. But at the end of it all, we should have faster, more efficient code, and be able to easily plugin different graphics backends, which is a win.


Dan said...

I think I'm slightly confused about the extra layers. Aren't Skia and Cairo themselves meant to be abstractions from their underlying backends, and therefore using one of them alleviates the need for another layer on top? If you settled on one of the two across the platforms would you still need Azure? Or if Azure could be written to utilise the different backends then would you still need Skia / Cairo in the midddle?

Manoj Mehta said...

Skia, Cairo, D2D, etc. expose functionality via different API. Azure, as I understand it, abstracts these differences and allows the codebase to call a uniform, rendering API regardless of underlying implementation. Think of Azure as the adapter between the rendering code in Firefox and the underlying graphics library/platform implementation.

Nick Cameron. said...

In reply to Dan, Manoj has it pretty much right. The motivation is that we are cross-platform, and we want to use different graphics libraries on different platforms, for e.g., Skia on Android, D2D on Windows, Cairo on Linux, Quartz on Mac, and so we need to abstract the graphics libraries one stage further. It would be nice to use the underlying backends directly, but this would be too much work - we don't want to implement our own code for bezier curves, for example. Finally, neither Cairo or Skia support all the backends we want to cover.

gutscheine zum ausdrucken said...

guter Kommentar