Handling scenarios with Stage3D (Molehill)

Yesterday, Terry Paton posted a note on Google Plus, about detecting different scenarios with Stage3D (Molehill), like is it running in software, or is Stage3D available in the Flash Player running my SWF ?

It actually reminded me that a little explanation of the different scenarions may be helpful. It may sound complex at the beginning, but actually it is not, once you will have integrated this into your code, you will be all set for all scenarios. The first scenario you want to handle, is when the configuration trying to play your content does not satisfy the hardware requirements. Keep in mind that Stage3D has a built-in automatic software fallback, meaning that, even if the drivers are blacklisted or if graphics card is not compatible, Stage3D will fallback to software and play the content, which guarantees you that your user will not end up with a black screen rendering nothing.

But it is actually very important to detect if you are running in software for multiple reasons :

  1. To inform the user about this, and letting him know that the performance/experience may not be the best of all, and that updating his drivers may highly improve performance.
  2. Or you can choose to fallback to software silently, without any warnings, and adapt the graphics in your application so that complex effects which are likely to run slowly on software are removed.

A good practice is to rely on Context3DRenderMode.AUTO, Stage3D will try to run on hardware, then fallback to software if the drivers are too old (released before January 1st, 2009), if the graphics card is not support Pixel Shader 2.x or if the graphics card chipset is blacklisted.

So we would write the following:

// listen to the context creation event
myStage3D.addEventListener(Event.CONTEXT3D_CREATE, onContextCreated);

// request the 3d context

// when the context is available, grab it
function onContextCreated ( e:Event ):void
    // grab the 3D context
    var context3D:Context3D = myStage3D.context3D;

    // are we running hardware of software ?
    var isHW:Boolean = context3D.driverInfo.toLowerCase().indexOf("software") == -1;

You may wonder why am I testing the software string using indexOf, the thing is that the exact string returned by driverInfo is : Software (Direct blitting)

So rather than testing the whole string with potential typos, we just look for the string "software" in it.

Now you have simple logic to detect if you are running in software or hardware. Now let's handle another scenario. Remember that the one thing which may fail to give you access to a Context3D object is the use of the wrong embed value (wmode). By using anything different than "direct", you will get a runtime exception when calling requestContext3D on the Stage3D object, so to handle such a scenario, just listen to the generic ErrorEvent.ERROR event:

// listen to the error
myStage3D.addEventListener(ErrorEvent.ERROR, onStage3DError);

// display message
function onStage3DError ( e:ErrorEvent ):void
    legend.text = "This content is not correctly embedded. Please change the wmode value to allow this content to run.";

Then, there is the device loss context to handle, happening when the graphics card resource is lost. It happens if the screen saver kicks in or when pressing CTRL+ATL+DEL on Windows. To handle this scenario, you need to simulate it and make sure your application re-initializes correctly in this scenario. To simulate a loss event, just leave the Event.CONTEXT3D_CREATE event listener on the stage3D object, then call context3D.dispose().

There is also a final situation where you do not want to force the upgrade to a specific Flash Player version, keep the same SWF requirement but detect if the player running your SWF has a specific API available. And as Si and Zwetan mentioned, you can write the following:

var stage3DAvailable:Boolean = ApplicationDomain.currentDomain.hasDefinition( "flash.display.Stage3D" );

Or even shorter for stage objects like StageVideo or Stage3D :

var stage3DAvailable:Boolean = stage.hasOwnProperty("stage3Ds");

And voila, you are all set for handling those situations within your Stage3D (Molehill) content.

Comments (11)

  1. ben w wrote:

    super useful!

    thanks for putting this little article together

    Tuesday, September 6, 2011 at 10:53 pm #
  2. While var stage3DAvailable:Boolean = stage.hasOwnProperty(“stage3Ds”); works, I highly suspect many will forget to wait for ADDED_TO_STAGE for their main sprites…..maybe a valuable addition ?

    Tuesday, September 6, 2011 at 11:10 pm #
  3. Kodiak wrote:

    Great! Maybe next time it would be nice to have strings like “Software (Direct blitting)” in a constant somewhere ;)

    Wednesday, September 7, 2011 at 10:55 am #
  4. erick wrote:

    I want to thank you for all your hard work and especially thank you for sharing your knowledge with the community. With that said I believe FP11 will bring much more hype to Flash again. As soon big name interactive agencies start utilizing this technology we are going to see some amazing stuff soon.

    Wednesday, September 7, 2011 at 8:15 pm #
  5. DonPaolo wrote:

    I know it has been asked a thousand times, but again: When on mobile?

    Cause this will be THE big thing to bring developers back to the flash platform.

    Say MAX 11, and I’m fine ;-)

    Sunday, September 11, 2011 at 11:18 pm #
  6. Hi Thibault,

    Thank your for the infos.
    I’m asking myself : is it possible to force flash11 to software rendering mode ? And if yes, how ?
    It would be nice to have a simple way to do this in development stage.

    Wednesday, September 14, 2011 at 9:37 pm #
  7. Just found this http://help.adobe.com/en_US/FlashPlatform/beta/reference/actionscript/3/flash/display/Stage3D.html#requestContext3D%28%29
    This seems to answer my own question ;-)
    I think this should be an option in 3d frameworks like Away3D4.

    Wednesday, September 14, 2011 at 10:03 pm #
  8. dknox wrote:

    For a “device loss” scenario I need to know WHEN this occurs or if the OS is responsible for the Event.CONTEXT3D_CREATE dispatch (as opposed to my explicit _stage3D.requestContext3D(Context3DRenderMode.AUTO) call). This is important because I need to know when to stop my onEnterFrame handler that renders my 3D content. I’ve tested by hitting Ctrl+Alt+Delete and upon return an error is thrown stating “Error #3694: The object was disposed by an earlier call of dispose() on it.”. How do I know when to shut off calls that are dependent on the assets loaded to the hardware? Is there another work around?

    Thursday, October 27, 2011 at 2:38 am #
  9. komelgman wrote:

    2 dknox:

    in your onEnterFrame handler check context3D.driverInfo == ‘Disposed’

    Saturday, November 12, 2011 at 3:40 am #
  10. johny wrote:

    Hello, I have problems trying to load a swf that targets fp11 inside my flex 3.6 sdk project…
    I change the playergloabls.swc for my flex project and trying to put “-swf-version=13″ but I get the error “Error: unknown configuration variable ‘swf-version”

    Does this mean I have to port my flex 3.6 project to 4.5.1 in order to load a simple swf that has stage3d content?

    Sunday, November 27, 2011 at 2:30 pm #
  11. stephen wrote:

    Is wmode=”direct” a required parameter to use Context3D at all? The way you worded your article, it sounded like if they were missing that parameter, the swf would fall back to software mode. However, I’ve tried running Stage3D apps in the browser, and without the wmode=”direct” parameter, I get a Context3D is not available exception. It doesn’t fall back to software mode in that case.

    Saturday, February 18, 2012 at 7:57 am #

Trackback/Pingback (1)

  1. Cool Stuff with the Flash Platform - 9/8/2011 | Remote Synthesis on Thursday, September 8, 2011 at 8:30 pm

    [...] of Stage3D, Adobe's Thibault Imbert shows you how to handle scenarios with Stage3D such as whether the users machine is using hardware rendering or the software rendering fallback or [...]