Amazing, so many things have happened in the Flash Player engineering team over the past year. Lots I would love to talk about. But the purpose of this post is to deep dive into a subject Kevin Lynch touched upon recently, specifically Mac performance and his comment about Core Animation. Whenever performance is mentioned in the context of Flash it gathers a lot of the attention and some of the technical background is lost in the PR.
So what’s the deal with Core Animation in Flash Player 10.1? Let’s look at how Apple’s documentation summarizes what Core Animation does:
Core Animation is an Objective-C framework that combines a high-performance compositing engine with a simple to use animation programming interface.
Sounds like perfect match for Flash does it not? So yes, Flash Player 10.1 is attempting to leverage this framework to work around a few specific technical issues we’ve had in Safari and all other browsers on OS X.
The drawing model jungle on OS X
Before going into more specifics of why we are going towards Core Animation lets get an overview about how plugins on OS X draw into the browser window. There 4 possible ways (compared to one on Windows):
- QuickDraw. Default mode used by Opera, older Firefox and Safari versions.
- Quartz 2D (a.k.a. Core Graphics). Supported by newer versions of Firefox and Safari.
- OpenGL. No browser I know of supports this properly today.
- Core Animation. Only available in Safari 4 + OS X 10.6 right now, with caveats in the current version.
In addition to these drawing models designers can embed Flash content in 3 different ways by specifying wmode:
Normal means that you can’t have overlapping HTML sitting on top of your SWF, Opaque allows it and Transparent means that the SWF is transparent and underlying HTML content will show through. Taking all these variables into account we come up with these tables which shows when a particular drawing model is used (and subject for change before we release Flash Player 10.1):
Flash Player 10.0:
|Safari 4||Firefox 3||Opera 10|
Flash Player 10.1:
|Safari 4 (*)||Firefox 3||Opera 10|
|Normal||Core Animation||Quartz 2D||QuickDraw|
|Opaque||Quartz 2D(**)||Quartz 2D||QuickDraw|
|Transparent||Quartz 2D(**)||Quartz 2D||QuickDraw|
(*) Actually using nightly builds of WebKit because support for Core Animation is work in progress.
(**) Core Animation is used when the SWF is the front most object on the HTML page.
What are the issues with Quartz 2D?
The basic premise of Quartz 2D as Apple describes it:
Quartz 2D is an advanced, two-dimensional drawing engine available for iPhone application development and to all Mac OS X application environments outside of the kernel. Quartz 2D provides low-level, lightweight 2D rendering with unmatched output fidelity regardless of display or printing device.
Quartz 2D is not designed for multimedia applications, like animation or video playback. That’s where OpenGL, Core Video, Core Animation shine. Safari’s use of Quartz 2D to draw HTML content makes perfect sense as its content is static in most cases. Everything works well until Flash comes into the picture. For instance when the Flash Player plays a SWF using the Quartz 2D drawing model is has to do so with the full involvement of the browser. The sequence of events looks like this (you can follow the stack traces in Shark):
- Whenever the Flash Player is ready to display a new frame, the Flash Player requests a refresh of its region using NPN_InvalidateRect.
- The browser adds the the rectangle provided by the Flash Player to its dirty region.
- The browser traverses its own display list (the HTML DOM) and paints every node which is part of the dirty region.
- When the browser finds a node with a Flash Player instance it first draws the HTML background and then posts an event to the Flash Player to tell it that it has to paint over the requested region now.
- The Flash Player then finally draws its frame.
So far so good, makes sense I hope. So what’s the technical issue? Think of a fairly complex HTML page, for instance a page with a CSS gradient in the background. Add to add a SWF which runs at 30 frames/sec. You will see that a lot of time is spent in the browser, not in the Flash Player. This is where Core Animation kicks in: step 3 and 4 pretty much go away (as long as the SWF is the top most object).
Core Animation in the Flash Player
Flash Player 10.1 implements the Core Animation drawing model to fix this technical issue, among others. Instead of using a CGImageRef + CGContextDrawImage to get the bits to screen we pass a CAOpenGLLayer to Safari and use an OpenGL texture of type GL_TEXTURE_RECTANGLE_ARB to get our bits to the screen.
The support for the Core Animation drawing model was originally driven by Apple and we have worked feverishly to finish the engineering work on both sides. Yes that’s right: This was and is a joint effort between Apple and Adobe engineers. Given the now almost perfect integration of Core Animation plugins into Safari I hope that future versions of the Flash Player will take advantage of more capabilities of OpenGL. And that without the requirement of setting any special wmode. I am pretty stoked about it.
As of today (2/10/2010) we are getting closer to having it stable enough for public consumption. That means though: You will need Flash Player 10.1, OS X 10.6 and updated version of Safari (or the nightly WebKit build), otherwise you will not see anything.
What difference does it really make?
This is by no means panacea for all performance issues in the Flash Player. Far from it. But it is a small step to a larger goal which is to improve the experience in the browser with the ever more complex web content out there. That said here is a comparison between Flash Player 10.0 and Flash 10.1 using this test case (this only works in Safari). Keep in mind that that is an extreme test case which has little to do with real world web content.
Flash Player 10.0 + nightly WebKit + OS X 10.6
Flash Player 10.1 + nightly WebKit + OS X 10.6
PS: You might have noticed that Core Animation is a Cocoa API. Yes, Flash Player 10.1 is a true Cocoa app now (with a Carbon fallback to support Firefox and Opera which are not Cocoa yet).