Skip to content

Instantly share code, notes, and snippets.

@rzubek
Last active December 19, 2015 22:09
Show Gist options
  • Save rzubek/6025532 to your computer and use it in GitHub Desktop.
Save rzubek/6025532 to your computer and use it in GitHub Desktop.
Helper class to query various Context3DProfiles, and figure out the highest one available for the current hardware configuration. Unfortunately Stage3D doesn't have a simple property we can look up, we have to do this cascading async kluge instead.
package
{
import flash.display.Stage;
import flash.display.Stage3D;
import flash.display3D.Context3DProfile;
import flash.display3D.Context3DRenderMode;
import flash.events.ErrorEvent;
import flash.events.Event;
import flash.utils.setTimeout;
public class Context3DDetector
{
private var _stage3d :Stage3D;
private var _successCallback :Function;
private var _profileBeingTested :String;
private var _profilesToTest :Vector.<String>;
private var _profile :String = "unknown";
private var _softwareMode :Boolean = false;
private var _driverInfo :String = "unknown";
public function Context3DDetector (stage :Stage)
{
_stage3d = (stage.stage3Ds.length > 0) ? stage.stage3Ds[0] : null;
}
public function get bestSupportedProfile () :String { return _profile; }
public function get supports4kTextures () :Boolean { return _profile == Context3DProfile.BASELINE_EXTENDED; }
public function get driverInfoDescription () :String { return _driverInfo; }
public function get softwareMode () :Boolean { return _softwareMode; }
/**
* Call this function to start hardware detection. After it's finished,
* the successCallback function will be called with no arguments,
* and public getters on this function will be ready for querying.
*/
public function start (successCallback :Function) :void {
_successCallback = successCallback;
// catastrophic failure
if (_stage3d == null) {
done(null, null);
return; // early return!
}
_profilesToTest = new <String> [
Context3DProfile.BASELINE_EXTENDED,
Context3DProfile.BASELINE,
Context3DProfile.BASELINE_CONSTRAINED
];
_stage3d.addEventListener(Event.CONTEXT3D_CREATE, onContextSuccess);
_stage3d.addEventListener(ErrorEvent.ERROR, onContextError);
detectProfile(_profilesToTest.shift());
}
private function detectProfile (profile :String) :void {
_profileBeingTested = profile;
setTimeout(function () :void {
_stage3d.requestContext3D(Context3DRenderMode.AUTO, profile);
}, 1);
}
private function onContextError (event :ErrorEvent) :void {
// clean up, and fall through to the next one
if (_stage3d.context3D != null) {
_stage3d.context3D.dispose(false);
}
if (_profilesToTest.length > 0) {
detectProfile(_profilesToTest.shift());
} else {
done(null, null);
}
}
private function onContextSuccess (event :Event) :void {
// we'll let the rendering engine reacquire it with its own settings
var driverInfo :String = null;
if (_stage3d.context3D != null) {
driverInfo = _stage3d.context3D.driverInfo;
_stage3d.context3D.dispose(false);
}
done(_profileBeingTested, driverInfo);
}
private function done (profile :String, driverInfo :String) :void {
if (_stage3d != null) {
_stage3d.removeEventListener(Event.CONTEXT3D_CREATE, onContextSuccess);
_stage3d.removeEventListener(ErrorEvent.ERROR, onContextError);
_stage3d = null;
}
_profilesToTest = null;
_profileBeingTested = null;
_profile = profile;
if (driverInfo != null) {
_driverInfo = driverInfo;
_softwareMode = (driverInfo.toLowerCase().indexOf("software") >= 0);
}
var callback :Function = _successCallback;
_successCallback = null;
setTimeout(callback, 1);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment