Merge m-c to b2ginbound a=merge
authorWes Kocher <wkocher@mozilla.com>
Wed, 01 Apr 2015 18:20:14 -0700
changeset 237226 aa869cc9fa8c50ffb99a4ec86bb07b7a7762ef18
parent 237225 23965fa6570e72c789b87feac1ea82c6ed2817ea (current diff)
parent 237167 702abe76d6a24ff8e20315277ff9d83098f7438c (diff)
child 237227 974921766e87a8fab18dd1b1184ada367cbb252b
push id57898
push usercbook@mozilla.com
push dateThu, 02 Apr 2015 12:14:17 +0000
treeherdermozilla-inbound@63c87250946e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone40.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge m-c to b2ginbound a=merge
gfx/thebes/gfxVR.cpp
gfx/thebes/gfxVR.h
gfx/thebes/ovr_capi_dynamic.h
toolkit/components/aboutcompartments/content/aboutCompartments.js
toolkit/components/aboutcompartments/content/aboutCompartments.xhtml
toolkit/components/aboutcompartments/jar.mn
toolkit/components/aboutcompartments/moz.build
toolkit/components/aboutcompartments/nsCompartmentInfo.cpp
toolkit/components/aboutcompartments/nsCompartmentInfo.h
toolkit/components/aboutcompartments/nsICompartmentInfo.idl
--- a/.gitignore
+++ b/.gitignore
@@ -3,16 +3,17 @@
 # Filenames that should be ignored wherever they appear
 *~
 *.pyc
 *.pyo
 TAGS
 tags
 ID
 .DS_Store*
+*.pdb
 
 # Vim swap files.
 .*.sw[a-z]
 
 # Emacs directory variable files.
 **/.dir-locals.el
 
 # User files that may appear at the root
--- a/b2g/installer/package-manifest.in
+++ b/b2g/installer/package-manifest.in
@@ -140,44 +140,43 @@
 @RESPATH@/components/components.manifest
 @RESPATH@/components/alerts.xpt
 #ifdef ACCESSIBILITY
 #ifdef XP_WIN32
 @BINPATH@/AccessibleMarshal.dll
 #endif
 @RESPATH@/components/accessibility.xpt
 #endif
-@RESPATH@/components/appshell.xpt
-@RESPATH@/components/appstartup.xpt
-@RESPATH@/components/autocomplete.xpt
-@RESPATH@/components/autoconfig.xpt
-@RESPATH@/components/browsercompsbase.xpt
-@RESPATH@/components/browser-element.xpt
-@RESPATH@/components/browser-feeds.xpt
-@RESPATH@/components/caps.xpt
-@RESPATH@/components/chardet.xpt
-@RESPATH@/components/chrome.xpt
-@RESPATH@/components/commandhandler.xpt
-@RESPATH@/components/commandlines.xpt
-@RESPATH@/components/compartments.xpt
-@RESPATH@/components/composer.xpt
-@RESPATH@/components/content_events.xpt
-@RESPATH@/components/content_html.xpt
-@RESPATH@/components/content_xslt.xpt
-@RESPATH@/components/cookie.xpt
-@RESPATH@/components/devtools_security.xpt
-@RESPATH@/components/directory.xpt
-@RESPATH@/components/diskspacewatcher.xpt
-@RESPATH@/components/docshell.xpt
-@RESPATH@/components/dom.xpt
-@RESPATH@/components/dom_activities.xpt
-@RESPATH@/components/dom_apps.xpt
-@RESPATH@/components/dom_audiochannel.xpt
-@RESPATH@/components/dom_base.xpt
-@RESPATH@/components/dom_system.xpt
+@BINPATH@/components/appshell.xpt
+@BINPATH@/components/appstartup.xpt
+@BINPATH@/components/autocomplete.xpt
+@BINPATH@/components/autoconfig.xpt
+@BINPATH@/components/browsercompsbase.xpt
+@BINPATH@/components/browser-element.xpt
+@BINPATH@/components/browser-feeds.xpt
+@BINPATH@/components/caps.xpt
+@BINPATH@/components/chardet.xpt
+@BINPATH@/components/chrome.xpt
+@BINPATH@/components/commandhandler.xpt
+@BINPATH@/components/commandlines.xpt
+@BINPATH@/components/composer.xpt
+@BINPATH@/components/content_events.xpt
+@BINPATH@/components/content_html.xpt
+@BINPATH@/components/content_xslt.xpt
+@BINPATH@/components/cookie.xpt
+@BINPATH@/components/devtools_security.xpt
+@BINPATH@/components/directory.xpt
+@BINPATH@/components/diskspacewatcher.xpt
+@BINPATH@/components/docshell.xpt
+@BINPATH@/components/dom.xpt
+@BINPATH@/components/dom_activities.xpt
+@BINPATH@/components/dom_apps.xpt
+@BINPATH@/components/dom_audiochannel.xpt
+@BINPATH@/components/dom_base.xpt
+@BINPATH@/components/dom_system.xpt
 #ifdef MOZ_WIDGET_GONK
 @RESPATH@/components/dom_wifi.xpt
 @RESPATH@/components/dom_system_gonk.xpt
 #endif
 #ifdef MOZ_B2G_RIL
 @RESPATH@/components/dom_wappush.xpt
 @RESPATH@/components/dom_mobileconnection.xpt
 #endif
@@ -321,16 +320,17 @@
 @RESPATH@/components/spellchecker.xpt
 @RESPATH@/components/storage.xpt
 @RESPATH@/components/telemetry.xpt
 @RESPATH@/components/toolkit_asyncshutdown.xpt
 @RESPATH@/components/toolkit_filewatcher.xpt
 @RESPATH@/components/toolkit_finalizationwitness.xpt
 @RESPATH@/components/toolkit_formautofill.xpt
 @RESPATH@/components/toolkit_osfile.xpt
+@RESPATH@/components/toolkit_perfmonitoring.xpt
 @RESPATH@/components/toolkit_xulstore.xpt
 @RESPATH@/components/toolkitprofile.xpt
 #ifdef MOZ_ENABLE_XREMOTE
 @RESPATH@/components/toolkitremote.xpt
 #endif
 @RESPATH@/components/txtsvc.xpt
 @RESPATH@/components/txmgr.xpt
 #ifdef MOZ_USE_NATIVE_UCONV
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -3774,18 +3774,17 @@
                                           charSet: aMessage.data.charSet,
                                           referrer: aMessage.data.referrer,
                                           referrerPolicy: aMessage.data.referrerPolicy,
                                           contentType: aMessage.data.contentType,
                                           contentDisposition: aMessage.data.contentDisposition,
                                         };
               let popup = browser.ownerDocument.getElementById("contentAreaContextMenu");
               let event = gContextMenuContentData.event;
-              let pos = browser.mapScreenCoordinatesFromContent(event.screenX, event.screenY);
-              popup.openPopupAtScreen(pos.x, pos.y, true);
+              popup.openPopupAtScreen(event.screenX, event.screenY, true);
               break;
             }
             case "DOMWebNotificationClicked": {
               let tab = this.getTabForBrowser(browser);
               if (!tab)
                 return;
               this.selectedTab = tab;
               window.focus();
--- a/browser/base/content/test/general/test_contextmenu_input.html
+++ b/browser/base/content/test/general/test_contextmenu_input.html
@@ -322,17 +322,17 @@ function waitForEvents(event)
 {
   if (event.type == "MozAfterPaint")
     painted = true;
   else if (event.type == "load")
     loaded = true;
   if (painted && loaded) {
     subwindow.removeEventListener("MozAfterPaint", waitForEvents, false);
     subwindow.onload = null;
-    startTest();
+    SimpleTest.waitForFocus(startTest, subwindow);
   }
 }
 
 var subwindow = window.open("data:text/html,<!DOCTYPE html><input><input spellcheck='true' value='prodkjfgigrty'><input spellcheck='true' value='foo'><input readonly spellcheck='false'>", "contextmenu-subtext", "width=600,height=700");
 subwindow.addEventListener("MozAfterPaint", waitForEvents, false);
 subwindow.onload = waitForEvents;
 
 SimpleTest.waitForExplicitFinish();
--- a/browser/base/content/test/social/browser_addons.js
+++ b/browser/base/content/test/social/browser_addons.js
@@ -1,12 +1,13 @@
 
 
 let AddonManager = Cu.import("resource://gre/modules/AddonManager.jsm", {}).AddonManager;
 let SocialService = Cu.import("resource://gre/modules/SocialService.jsm", {}).SocialService;
+let AddonWatcher = Cu.import("resource://gre/modules/AddonWatcher.jsm", {}).AddonWatcher;
 
 const ADDON_TYPE_SERVICE     = "service";
 const ID_SUFFIX              = "@services.mozilla.org";
 const STRING_TYPE_NAME       = "type.%ID%.name";
 const XPINSTALL_URL = "chrome://mozapps/content/xpinstall/xpinstallConfirm.xul";
 
 let manifest = {
   name: "provider 1",
--- a/browser/components/loop/content/shared/css/conversation.css
+++ b/browser/components/loop/content/shared/css/conversation.css
@@ -967,21 +967,24 @@ html, .fx-embedded, #main,
 
 .standalone .room-conversation-wrapper .room-inner-info-area a.btn {
   padding: .5em 3em .3em 3em;
   border-radius: 3px;
   font-weight: normal;
   max-width: 400px;
 }
 
-.standalone .room-conversation h2.room-name {
+.standalone .room-conversation h2.room-name,
+.standalone .room-conversation h2.room-info-failure {
   position: absolute;
   display: inline-block;
   top: 0;
-  right: 0;
+  right: 10px;
+  /* 20px is 10px for left and right margins. */
+  width: calc(25% - 20px);
   color: #fff;
   z-index: 2000000;
   font-size: 1.2em;
   padding: .4em;
 }
 
 .standalone .room-conversation .media {
   background: #000;
--- a/browser/components/loop/content/shared/js/actions.js
+++ b/browser/components/loop/content/shared/js/actions.js
@@ -38,17 +38,18 @@ loop.shared.actions = (function() {
     GetWindowData: Action.define("getWindowData", {
       windowId: String
     }),
 
     /**
      * Extract the token information and type for the standalone window
      */
     ExtractTokenInfo: Action.define("extractTokenInfo", {
-      windowPath: String
+      windowPath: String,
+      windowHash: String
     }),
 
     /**
      * Used to pass round the window data so that stores can
      * record the appropriate data.
      */
     SetupWindowData: Action.define("setupWindowData", {
       windowId: String,
@@ -60,16 +61,17 @@ loop.shared.actions = (function() {
       // data.
     }),
 
     /**
      * Used to fetch the data from the server for a room or call for the
      * token.
      */
     FetchServerData: Action.define("fetchServerData", {
+      // cryptoKey: String - Optional.
       token: String,
       windowType: String
     }),
 
     /**
      * Used to signal when the window is being unloaded.
      */
     WindowUnload: Action.define("windowUnload", {
@@ -381,16 +383,17 @@ loop.shared.actions = (function() {
 
     /**
      * Updates the room information when it is received.
      * XXX: should move to some roomActions module - refs bug 1079284
      *
      * @see https://wiki.mozilla.org/Loop/Architecture/Rooms#GET_.2Frooms.2F.7Btoken.7D
      */
     UpdateRoomInfo: Action.define("updateRoomInfo", {
+      // context: Object - Optional.
       // roomName: String - Optional.
       roomOwner: String,
       roomUrl: String
     }),
 
     /**
      * Starts the process for the user to join the room.
      * XXX: should move to some roomActions module - refs bug 1079284
--- a/browser/components/loop/content/shared/js/activeRoomStore.js
+++ b/browser/components/loop/content/shared/js/activeRoomStore.js
@@ -6,25 +6,28 @@
 
 var loop = loop || {};
 loop.store = loop.store || {};
 
 loop.store.ActiveRoomStore = (function() {
   "use strict";
 
   var sharedActions = loop.shared.actions;
+  var crypto = loop.crypto;
   var FAILURE_DETAILS = loop.shared.utils.FAILURE_DETAILS;
   var SCREEN_SHARE_STATES = loop.shared.utils.SCREEN_SHARE_STATES;
 
   // Error numbers taken from
   // https://github.com/mozilla-services/loop-server/blob/master/loop/errno.json
   var REST_ERRNOS = loop.shared.utils.REST_ERRNOS;
 
   var ROOM_STATES = loop.store.ROOM_STATES;
 
+  var ROOM_INFO_FAILURES = loop.shared.utils.ROOM_INFO_FAILURES;
+
   /**
    * Active room store.
    *
    * @param {loop.Dispatcher} dispatcher  The dispatcher for dispatching actions
    *                                      and registering to consume actions.
    * @param {Object} options Options object:
    * - {mozLoop}     mozLoop    The MozLoop API object.
    * - {OTSdkDriver} sdkDriver  The SDK driver instance.
@@ -71,17 +74,21 @@ loop.store.ActiveRoomStore = (function()
         // Tracks if the room has been used during this
         // session. 'Used' means at least one call has been placed
         // with it. Entering and leaving the room without seeing
         // anyone is not considered as 'used'
         used: false,
         localVideoDimensions: {},
         remoteVideoDimensions: {},
         screenSharingState: SCREEN_SHARE_STATES.INACTIVE,
-        receivingScreenShare: false
+        receivingScreenShare: false,
+        // The roomCryptoKey to decode the context data if necessary.
+        roomCryptoKey: null,
+        // Room information failed to be obtained for a reason. See ROOM_INFO_FAILURES.
+        roomInfoFailure: null
       };
     },
 
     /**
      * Handles a room failure.
      *
      * @param {sharedActions.RoomFailure} actionData
      */
@@ -194,35 +201,83 @@ loop.store.ActiveRoomStore = (function()
         // Nothing for us to do here, leave it to other stores.
         return;
       }
 
       this._registerPostSetupActions();
 
       this.setStoreState({
         roomToken: actionData.token,
+        roomCryptoKey: actionData.cryptoKey,
         roomState: ROOM_STATES.READY
       });
 
       this._mozLoop.rooms.on("update:" + actionData.roomToken,
         this._handleRoomUpdate.bind(this));
       this._mozLoop.rooms.on("delete:" + actionData.roomToken,
         this._handleRoomDelete.bind(this));
 
-      this._mozLoop.rooms.get(this._storeState.roomToken,
-        function(err, result) {
-          if (err) {
-            // XXX Bug 1110937 will want to handle the error results here
-            // e.g. room expired/invalid.
-            console.error("Failed to get room data:", err);
-            return;
-          }
+      this._getRoomDataForStandalone();
+    },
+
+    _getRoomDataForStandalone: function() {
+      this._mozLoop.rooms.get(this._storeState.roomToken, function(err, result) {
+        if (err) {
+          // XXX Bug 1110937 will want to handle the error results here
+          // e.g. room expired/invalid.
+          console.error("Failed to get room data:", err);
+          return;
+        }
+
+        var roomInfoData = new sharedActions.UpdateRoomInfo({
+          roomOwner: result.roomOwner,
+          roomUrl: result.roomUrl
+        });
+
+        if (!result.context && !result.roomName) {
+          roomInfoData.roomInfoFailure = ROOM_INFO_FAILURES.NO_DATA;
+          this.dispatcher.dispatch(roomInfoData);
+          return;
+        }
 
-          this.dispatcher.dispatch(new sharedActions.UpdateRoomInfo(result));
-        }.bind(this));
+        // This handles 'legacy', non-encrypted room names.
+        if (result.roomName && !result.context) {
+          roomInfoData.roomName = result.roomName;
+          this.dispatcher.dispatch(roomInfoData);
+          return;
+        }
+
+        if (!crypto.isSupported()) {
+          roomInfoData.roomInfoFailure = ROOM_INFO_FAILURES.WEB_CRYPTO_UNSUPPORTED;
+          this.dispatcher.dispatch(roomInfoData);
+          return;
+        }
+
+        var roomCryptoKey = this.getStoreState("roomCryptoKey");
+
+        if (!roomCryptoKey) {
+          roomInfoData.roomInfoFailure = ROOM_INFO_FAILURES.NO_CRYPTO_KEY;
+          this.dispatcher.dispatch(roomInfoData);
+          return;
+        }
+
+        var dispatcher = this.dispatcher;
+
+        crypto.decryptBytes(roomCryptoKey, result.context.value)
+              .then(function(decryptedResult) {
+          var realResult = JSON.parse(decryptedResult);
+
+          roomInfoData.roomName = realResult.roomName;
+
+          dispatcher.dispatch(roomInfoData);
+        }, function(err) {
+          roomInfoData.roomInfoFailure = ROOM_INFO_FAILURES.DECRYPT_FAILED;
+          dispatcher.dispatch(roomInfoData);
+        });
+      }.bind(this));
     },
 
     /**
      * Handles the setupRoomInfo action. Sets up the initial room data and
      * sets the state to `READY`.
      *
      * @param {sharedActions.SetupRoomInfo} actionData
      */
@@ -249,16 +304,17 @@ loop.store.ActiveRoomStore = (function()
 
     /**
      * Handles the updateRoomInfo action. Updates the room data.
      *
      * @param {sharedActions.UpdateRoomInfo} actionData
      */
     updateRoomInfo: function(actionData) {
       this.setStoreState({
+        roomInfoFailure: actionData.roomInfoFailure,
         roomName: actionData.roomName,
         roomOwner: actionData.roomOwner,
         roomUrl: actionData.roomUrl
       });
     },
 
     /**
      * Handles room updates notified by the mozLoop rooms API.
--- a/browser/components/loop/content/shared/js/utils.js
+++ b/browser/components/loop/content/shared/js/utils.js
@@ -38,16 +38,27 @@ loop.shared.utils = (function(mozL10n) {
     MEDIA_DENIED: "reason-media-denied",
     UNABLE_TO_PUBLISH_MEDIA: "unable-to-publish-media",
     COULD_NOT_CONNECT: "reason-could-not-connect",
     NETWORK_DISCONNECTED: "reason-network-disconnected",
     EXPIRED_OR_INVALID: "reason-expired-or-invalid",
     UNKNOWN: "reason-unknown"
   };
 
+  var ROOM_INFO_FAILURES = {
+    // There's no data available from the server.
+    NO_DATA: "no_data",
+    // WebCrypto is unsupported in this browser.
+    WEB_CRYPTO_UNSUPPORTED: "web_crypto_unsupported",
+    // The room is missing the crypto key information.
+    NO_CRYPTO_KEY: "no_crypto_key",
+    // Decryption failed.
+    DECRYPT_FAILED: "decrypt_failed"
+  };
+
   var STREAM_PROPERTIES = {
     VIDEO_DIMENSIONS: "videoDimensions",
     HAS_AUDIO: "hasAudio",
     HAS_VIDEO: "hasVideo"
   };
 
   var SCREEN_SHARE_STATES = {
     INACTIVE: "ss-inactive",
@@ -392,16 +403,17 @@ loop.shared.utils = (function(mozL10n) {
 
   return {
     CALL_TYPES: CALL_TYPES,
     FAILURE_DETAILS: FAILURE_DETAILS,
     REST_ERRNOS: REST_ERRNOS,
     WEBSOCKET_REASONS: WEBSOCKET_REASONS,
     STREAM_PROPERTIES: STREAM_PROPERTIES,
     SCREEN_SHARE_STATES: SCREEN_SHARE_STATES,
+    ROOM_INFO_FAILURES: ROOM_INFO_FAILURES,
     composeCallUrlEmail: composeCallUrlEmail,
     formatDate: formatDate,
     getBoolPreference: getBoolPreference,
     isChrome: isChrome,
     isFirefox: isFirefox,
     isFirefoxOS: isFirefoxOS,
     isOpera: isOpera,
     getUnsupportedPlatform: getUnsupportedPlatform,
--- a/browser/components/loop/standalone/content/index.html
+++ b/browser/components/loop/standalone/content/index.html
@@ -103,16 +103,17 @@
     <script type="text/javascript" src="shared/libs/react-0.12.2.js"></script>
     <script type="text/javascript" src="shared/libs/jquery-2.1.0.js"></script>
     <script type="text/javascript" src="shared/libs/lodash-2.4.1.js"></script>
     <script type="text/javascript" src="shared/libs/backbone-1.1.2.js"></script>
 
     <!-- app scripts -->
     <script type="text/javascript" src="config.js"></script>
     <script type="text/javascript" src="shared/js/utils.js"></script>
+    <script type="text/javascript" src="shared/js/crypto.js"></script>
     <script type="text/javascript" src="shared/js/models.js"></script>
     <script type="text/javascript" src="shared/js/mixins.js"></script>
     <script type="text/javascript" src="shared/js/feedbackApiClient.js"></script>
     <script type="text/javascript" src="shared/js/actions.js"></script>
     <script type="text/javascript" src="shared/js/validate.js"></script>
     <script type="text/javascript" src="shared/js/dispatcher.js"></script>
     <script type="text/javascript" src="shared/js/websocket.js"></script>
     <script type="text/javascript" src="shared/js/otSdkDriver.js"></script>
--- a/browser/components/loop/standalone/content/js/standaloneAppStore.js
+++ b/browser/components/loop/standalone/content/js/standaloneAppStore.js
@@ -91,18 +91,30 @@ loop.store.StandaloneAppStore = (functio
             windowType = "room";
           }
         }
       }
       return [windowType, match && match[1] ? match[1] : null];
     },
 
     /**
+     * Extracts the crypto key from the hash for the page.
+     */
+    _extractCryptoKey: function(windowHash) {
+      if (windowHash && windowHash[0] === "#") {
+        return windowHash.substring(1, windowHash.length);
+      }
+
+      return null;
+    },
+
+    /**
      * Handles the extract token info action - obtains the token information
-     * and its type; updates the store and notifies interested components.
+     * and its type; extracts any crypto information; updates the store and
+     * notifies interested components.
      *
      * @param {sharedActions.GetWindowData} actionData The action data
      */
     extractTokenInfo: function(actionData) {
       var windowType = "home";
       var token;
 
       // Check if we're on a supported device/platform.
@@ -130,16 +142,17 @@ loop.store.StandaloneAppStore = (functio
         isFirefox: sharedUtils.isFirefox(navigator.userAgent),
         unsupportedPlatform: unsupportedPlatform
       });
 
       // If we've not got a window ID, don't dispatch the action, as we don't need
       // it.
       if (token) {
         this._dispatcher.dispatch(new loop.shared.actions.FetchServerData({
+          cryptoKey: this._extractCryptoKey(actionData.windowHash),
           token: token,
           windowType: windowType
         }));
       }
     }
   }, Backbone.Events);
 
   return StandaloneAppStore;
--- a/browser/components/loop/standalone/content/js/standaloneRoomViews.js
+++ b/browser/components/loop/standalone/content/js/standaloneRoomViews.js
@@ -7,16 +7,17 @@
 /* global loop:true, React */
 /* jshint newcap:false, maxlen:false */
 
 var loop = loop || {};
 loop.standaloneRoomViews = (function(mozL10n) {
   "use strict";
 
   var FAILURE_DETAILS = loop.shared.utils.FAILURE_DETAILS;
+  var ROOM_INFO_FAILURES = loop.shared.utils.ROOM_INFO_FAILURES;
   var ROOM_STATES = loop.store.ROOM_STATES;
   var sharedActions = loop.shared.actions;
   var sharedMixins = loop.shared.mixins;
   var sharedViews = loop.shared.views;
 
   var StandaloneRoomInfoArea = React.createClass({displayName: "StandaloneRoomInfoArea",
     propTypes: {
       isFirefox: React.PropTypes.bool.isRequired,
@@ -193,16 +194,39 @@ loop.standaloneRoomViews = (function(moz
         React.createElement("footer", null, 
           React.createElement("p", {dangerouslySetInnerHTML: {__html: this._getContent()}}), 
           React.createElement("div", {className: "footer-logo"})
         )
       );
     }
   });
 
+  var StandaloneRoomContextView = React.createClass({displayName: "StandaloneRoomContextView",
+    propTypes: {
+      roomName: React.PropTypes.string,
+      roomInfoFailure: React.PropTypes.string
+    },
+
+    render: function() {
+      if (this.props.roomInfoFailure === ROOM_INFO_FAILURES.WEB_CRYPTO_UNSUPPORTED) {
+        return (React.createElement("h2", {className: "room-info-failure"}, 
+          mozL10n.get("room_information_failure_unsupported_browser")
+        ));
+      } else if (this.props.roomInfoFailure) {
+        return (React.createElement("h2", {className: "room-info-failure"}, 
+          mozL10n.get("room_information_failure_not_available")
+        ));
+      }
+
+      return (
+        React.createElement("h2", {className: "room-name"}, this.props.roomName)
+      );
+    }
+  });
+
   var StandaloneRoomView = React.createClass({displayName: "StandaloneRoomView",
     mixins: [
       Backbone.Events,
       sharedMixins.MediaSetupMixin,
       sharedMixins.RoomsAudioMixin
     ],
 
     propTypes: {
@@ -453,17 +477,18 @@ loop.standaloneRoomViews = (function(moz
           React.createElement(StandaloneRoomInfoArea, {roomState: this.state.roomState, 
                                   failureReason: this.state.failureReason, 
                                   joinRoom: this.joinRoom, 
                                   isFirefox: this.props.isFirefox, 
                                   activeRoomStore: this.props.activeRoomStore, 
                                   roomUsed: this.state.used}), 
           React.createElement("div", {className: "video-layout-wrapper"}, 
             React.createElement("div", {className: "conversation room-conversation"}, 
-              React.createElement("h2", {className: "room-name"}, this.state.roomName), 
+              React.createElement(StandaloneRoomContextView, {roomName: this.state.roomName, 
+                                         roomInfoFailure: this.state.roomInfoFailure}), 
               React.createElement("div", {className: "media nested"}, 
                 React.createElement("span", {className: "self-view-hidden-message"}, 
                   mozL10n.get("self_view_hidden_message")
                 ), 
                 React.createElement("div", {className: "video_wrapper remote_wrapper"}, 
                   React.createElement("div", {className: remoteStreamClasses}), 
                   React.createElement("div", {className: screenShareStreamClasses})
                 ), 
@@ -486,11 +511,12 @@ loop.standaloneRoomViews = (function(moz
             onMarketplaceMessage: this.state.onMarketplaceMessage}), 
           React.createElement(StandaloneRoomFooter, null)
         )
       );
     }
   });
 
   return {
+    StandaloneRoomContextView: StandaloneRoomContextView,
     StandaloneRoomView: StandaloneRoomView
   };
 })(navigator.mozL10n);
--- a/browser/components/loop/standalone/content/js/standaloneRoomViews.jsx
+++ b/browser/components/loop/standalone/content/js/standaloneRoomViews.jsx
@@ -7,16 +7,17 @@
 /* global loop:true, React */
 /* jshint newcap:false, maxlen:false */
 
 var loop = loop || {};
 loop.standaloneRoomViews = (function(mozL10n) {
   "use strict";
 
   var FAILURE_DETAILS = loop.shared.utils.FAILURE_DETAILS;
+  var ROOM_INFO_FAILURES = loop.shared.utils.ROOM_INFO_FAILURES;
   var ROOM_STATES = loop.store.ROOM_STATES;
   var sharedActions = loop.shared.actions;
   var sharedMixins = loop.shared.mixins;
   var sharedViews = loop.shared.views;
 
   var StandaloneRoomInfoArea = React.createClass({
     propTypes: {
       isFirefox: React.PropTypes.bool.isRequired,
@@ -193,16 +194,39 @@ loop.standaloneRoomViews = (function(moz
         <footer>
           <p dangerouslySetInnerHTML={{__html: this._getContent()}}></p>
           <div className="footer-logo" />
         </footer>
       );
     }
   });
 
+  var StandaloneRoomContextView = React.createClass({
+    propTypes: {
+      roomName: React.PropTypes.string,
+      roomInfoFailure: React.PropTypes.string
+    },
+
+    render: function() {
+      if (this.props.roomInfoFailure === ROOM_INFO_FAILURES.WEB_CRYPTO_UNSUPPORTED) {
+        return (<h2 className="room-info-failure">
+          {mozL10n.get("room_information_failure_unsupported_browser")}
+        </h2>);
+      } else if (this.props.roomInfoFailure) {
+        return (<h2 className="room-info-failure">
+          {mozL10n.get("room_information_failure_not_available")}
+        </h2>);
+      }
+
+      return (
+        <h2 className="room-name">{this.props.roomName}</h2>
+      );
+    }
+  });
+
   var StandaloneRoomView = React.createClass({
     mixins: [
       Backbone.Events,
       sharedMixins.MediaSetupMixin,
       sharedMixins.RoomsAudioMixin
     ],
 
     propTypes: {
@@ -453,17 +477,18 @@ loop.standaloneRoomViews = (function(moz
           <StandaloneRoomInfoArea roomState={this.state.roomState}
                                   failureReason={this.state.failureReason}
                                   joinRoom={this.joinRoom}
                                   isFirefox={this.props.isFirefox}
                                   activeRoomStore={this.props.activeRoomStore}
                                   roomUsed={this.state.used} />
           <div className="video-layout-wrapper">
             <div className="conversation room-conversation">
-              <h2 className="room-name">{this.state.roomName}</h2>
+              <StandaloneRoomContextView roomName={this.state.roomName}
+                                         roomInfoFailure={this.state.roomInfoFailure} />
               <div className="media nested">
                 <span className="self-view-hidden-message">
                   {mozL10n.get("self_view_hidden_message")}
                 </span>
                 <div className="video_wrapper remote_wrapper">
                   <div className={remoteStreamClasses}></div>
                   <div className={screenShareStreamClasses}></div>
                 </div>
@@ -486,11 +511,12 @@ loop.standaloneRoomViews = (function(moz
             onMarketplaceMessage={this.state.onMarketplaceMessage} />
           <StandaloneRoomFooter />
         </div>
       );
     }
   });
 
   return {
+    StandaloneRoomContextView: StandaloneRoomContextView,
     StandaloneRoomView: StandaloneRoomView
   };
 })(navigator.mozL10n);
--- a/browser/components/loop/standalone/content/js/webapp.js
+++ b/browser/components/loop/standalone/content/js/webapp.js
@@ -1104,17 +1104,18 @@ loop.webapp = (function($, _, OT, mozL10
     // Set the 'lang' and 'dir' attributes to <html> when the page is translated
     document.documentElement.lang = mozL10n.language.code;
     document.documentElement.dir = mozL10n.language.direction;
     document.title = mozL10n.get("clientShortname2");
 
     var locationData = sharedUtils.locationData();
 
     dispatcher.dispatch(new sharedActions.ExtractTokenInfo({
-      windowPath: locationData.pathname
+      windowPath: locationData.pathname,
+      windowHash: locationData.hash
     }));
   }
 
   return {
     CallUrlExpiredView: CallUrlExpiredView,
     PendingConversationView: PendingConversationView,
     GumPromptConversationView: GumPromptConversationView,
     WaitingConversationView: WaitingConversationView,
--- a/browser/components/loop/standalone/content/js/webapp.jsx
+++ b/browser/components/loop/standalone/content/js/webapp.jsx
@@ -1104,17 +1104,18 @@ loop.webapp = (function($, _, OT, mozL10
     // Set the 'lang' and 'dir' attributes to <html> when the page is translated
     document.documentElement.lang = mozL10n.language.code;
     document.documentElement.dir = mozL10n.language.direction;
     document.title = mozL10n.get("clientShortname2");
 
     var locationData = sharedUtils.locationData();
 
     dispatcher.dispatch(new sharedActions.ExtractTokenInfo({
-      windowPath: locationData.pathname
+      windowPath: locationData.pathname,
+      windowHash: locationData.hash
     }));
   }
 
   return {
     CallUrlExpiredView: CallUrlExpiredView,
     PendingConversationView: PendingConversationView,
     GumPromptConversationView: GumPromptConversationView,
     WaitingConversationView: WaitingConversationView,
--- a/browser/components/loop/standalone/content/l10n/en-US/loop.properties
+++ b/browser/components/loop/standalone/content/l10n/en-US/loop.properties
@@ -122,16 +122,18 @@ rooms_panel_title=Choose a conversation 
 rooms_room_full_label=There are already two people in this conversation.
 rooms_room_full_call_to_action_nonFx_label=Download {{brandShortname}} to start your own
 rooms_room_full_call_to_action_label=Learn more about {{clientShortname}} »
 rooms_room_joined_label=Someone has joined the conversation!
 rooms_room_join_label=Join the conversation
 rooms_display_name_guest=Guest
 rooms_unavailable_notification_message=Sorry, you cannot join this conversation. The link may be expired or invalid.
 rooms_media_denied_message=We could not get access to your microphone or camera. Please reload the page to try again.
+room_information_failure_not_available=No information about this conversation is available. Please request a new link from the person who sent it to you.
+room_information_failure_unsupported_browser=Your browser cannot access any information about this conversation. Please make sure you're using the latest version.
 
 ## LOCALIZATION_NOTE(standalone_title_with_status): {{clientShortname}} will be
 ## replaced by the brand name and {{currentStatus}} will be replaced
 ## by the current call status (Connecting, Ringing, etc.)
 standalone_title_with_status={{clientShortname}} — {{currentStatus}}
 status_in_conversation=In conversation
 status_conversation_ended=Conversation ended
 status_error=Something went wrong
--- a/browser/components/loop/test/shared/activeRoomStore_test.js
+++ b/browser/components/loop/test/shared/activeRoomStore_test.js
@@ -5,16 +5,17 @@ var sharedActions = loop.shared.actions;
 
 describe("loop.store.ActiveRoomStore", function () {
   "use strict";
 
   var REST_ERRNOS = loop.shared.utils.REST_ERRNOS;
   var ROOM_STATES = loop.store.ROOM_STATES;
   var FAILURE_DETAILS = loop.shared.utils.FAILURE_DETAILS;
   var SCREEN_SHARE_STATES = loop.shared.utils.SCREEN_SHARE_STATES;
+  var ROOM_INFO_FAILURES = loop.shared.utils.ROOM_INFO_FAILURES;
   var sandbox, dispatcher, store, fakeMozLoop, fakeSdkDriver;
   var fakeMultiplexGum;
 
   beforeEach(function() {
     sandbox = sinon.sandbox.create();
     sandbox.useFakeTimers();
 
     dispatcher = new loop.Dispatcher();
@@ -342,30 +343,137 @@ describe("loop.store.ActiveRoomStore", f
     });
 
     it("should call mozLoop.rooms.get to get the room data", function() {
       store.fetchServerData(fetchServerAction);
 
       sinon.assert.calledOnce(fakeMozLoop.rooms.get);
     });
 
-    it("should dispatch UpdateRoomInfo if mozLoop.rooms.get is successful", function() {
-      var roomDetails = {
-        roomName: "fakeName",
-        roomUrl: "http://invalid",
-        roomOwner: "gavin"
-      };
-
-      fakeMozLoop.rooms.get.callsArgWith(1, null, roomDetails);
+    it("should dispatch an UpdateRoomInfo message with 'no data' failure if neither roomName nor context are supplied", function() {
+      fakeMozLoop.rooms.get.callsArgWith(1, null, {
+        roomOwner: "Dan",
+        roomUrl: "http://invalid"
+      });
 
       store.fetchServerData(fetchServerAction);
 
       sinon.assert.calledOnce(dispatcher.dispatch);
       sinon.assert.calledWithExactly(dispatcher.dispatch,
-        new sharedActions.UpdateRoomInfo(roomDetails));
+        new sharedActions.UpdateRoomInfo({
+          roomInfoFailure: ROOM_INFO_FAILURES.NO_DATA,
+          roomOwner: "Dan",
+          roomUrl: "http://invalid"
+        }));
+    });
+
+    describe("mozLoop.rooms.get returns roomName as a separate field (no context)", function() {
+      it("should dispatch UpdateRoomInfo if mozLoop.rooms.get is successful", function() {
+        var roomDetails = {
+          roomName: "fakeName",
+          roomUrl: "http://invalid",
+          roomOwner: "gavin"
+        };
+
+        fakeMozLoop.rooms.get.callsArgWith(1, null, roomDetails);
+
+        store.fetchServerData(fetchServerAction);
+
+        sinon.assert.calledOnce(dispatcher.dispatch);
+        sinon.assert.calledWithExactly(dispatcher.dispatch,
+          new sharedActions.UpdateRoomInfo(roomDetails));
+      });
+    });
+
+    describe("mozLoop.rooms.get returns encryptedContext", function() {
+      var roomDetails, expectedDetails;
+
+      beforeEach(function() {
+        roomDetails = {
+          context: {
+            value: "fakeContext"
+          },
+          roomUrl: "http://invalid",
+          roomOwner: "Mark"
+        };
+        expectedDetails = {
+          roomUrl: "http://invalid",
+          roomOwner: "Mark"
+        };
+
+        fakeMozLoop.rooms.get.callsArgWith(1, null, roomDetails);
+
+        sandbox.stub(loop.crypto, "isSupported").returns(true);
+      });
+
+      it("should dispatch UpdateRoomInfo message with 'unsupported' failure if WebCrypto is unsupported", function() {
+        loop.crypto.isSupported.returns(false);
+
+        store.fetchServerData(fetchServerAction);
+
+        sinon.assert.calledOnce(dispatcher.dispatch);
+        sinon.assert.calledWithExactly(dispatcher.dispatch,
+          new sharedActions.UpdateRoomInfo(_.extend({
+            roomInfoFailure: ROOM_INFO_FAILURES.WEB_CRYPTO_UNSUPPORTED
+          }, expectedDetails)));
+      });
+
+      it("should dispatch UpdateRoomInfo message with 'no crypto key' failure if there is no crypto key", function() {
+        store.fetchServerData(fetchServerAction);
+
+        sinon.assert.calledOnce(dispatcher.dispatch);
+        sinon.assert.calledWithExactly(dispatcher.dispatch,
+          new sharedActions.UpdateRoomInfo(_.extend({
+            roomInfoFailure: ROOM_INFO_FAILURES.NO_CRYPTO_KEY
+          }, expectedDetails)));
+      });
+
+      it("should dispatch UpdateRoomInfo message with 'decrypt failed' failure if decryption failed", function() {
+        fetchServerAction.cryptoKey = "fakeKey";
+
+        // This is a work around to turn promise into a sync action to make handling test failures
+        // easier.
+        sandbox.stub(loop.crypto, "decryptBytes", function() {
+          return {
+            then: function(resolve, reject) {
+              reject(new Error("Operation unsupported"));
+            }
+          };
+        });
+
+        store.fetchServerData(fetchServerAction);
+
+        sinon.assert.calledOnce(dispatcher.dispatch);
+        sinon.assert.calledWithExactly(dispatcher.dispatch,
+          new sharedActions.UpdateRoomInfo(_.extend({
+            roomInfoFailure: ROOM_INFO_FAILURES.DECRYPT_FAILED
+          }, expectedDetails)));
+      });
+
+      it("should dispatch UpdateRoomInfo message with the room name if decryption was successful", function() {
+        fetchServerAction.cryptoKey = "fakeKey";
+
+        // This is a work around to turn promise into a sync action to make handling test failures
+        // easier.
+        sandbox.stub(loop.crypto, "decryptBytes", function() {
+          return {
+            then: function(resolve, reject) {
+              resolve(JSON.stringify({roomName: "The wonderful Loopy room"}));
+            }
+          };
+        });
+
+        store.fetchServerData(fetchServerAction);
+
+        sinon.assert.calledOnce(dispatcher.dispatch);
+        sinon.assert.calledWithExactly(dispatcher.dispatch,
+          new sharedActions.UpdateRoomInfo(_.extend({
+            roomName: "The wonderful Loopy room"
+          }, expectedDetails)));
+      });
     });
   });
 
   describe("#feedbackComplete", function() {
     it("should reset the room store state", function() {
       var initialState = store.getInitialStoreState();
       store.setStoreState({
         roomState: ROOM_STATES.ENDED,
--- a/browser/components/loop/test/standalone/standaloneAppStore_test.js
+++ b/browser/components/loop/test/standalone/standaloneAppStore_test.js
@@ -49,17 +49,18 @@ describe("loop.store.StandaloneAppStore"
     });
   });
 
   describe("#extractTokenInfo", function() {
     var store, fakeGetWindowData, fakeSdk, fakeConversation, helper;
 
     beforeEach(function() {
       fakeGetWindowData = {
-        windowPath: ""
+        windowPath: "",
+        windowHash: ""
       };
 
       sandbox.stub(loop.shared.utils, "getUnsupportedPlatform").returns();
       sandbox.stub(loop.shared.utils, "isFirefox").returns(true);
 
       fakeSdk = {
         checkSystemRequirements: sinon.stub().returns(true)
       };
@@ -172,41 +173,60 @@ describe("loop.store.StandaloneAppStore"
           new sharedActions.ExtractTokenInfo(fakeGetWindowData));
 
         sinon.assert.calledOnce(fakeConversation.set);
         sinon.assert.calledWithExactly(fakeConversation.set, {
           loopToken: "fakeroomtoken"
         });
       });
 
-    it("should set the loopToken on the conversation for call paths",
+    it("should dispatch a FetchServerData action for call paths",
       function() {
         fakeGetWindowData.windowPath = "/c/fakecalltoken";
 
         store.extractTokenInfo(
           new sharedActions.ExtractTokenInfo(fakeGetWindowData));
 
         sinon.assert.calledOnce(dispatcher.dispatch);
         sinon.assert.calledWithExactly(dispatcher.dispatch,
           new sharedActions.FetchServerData({
+            cryptoKey: null,
             windowType: "outgoing",
             token: "fakecalltoken"
           }));
       });
 
-    it("should set the loopToken on the conversation for room paths",
+    it("should dispatch a FetchServerData action for room paths",
       function() {
-        fakeGetWindowData.windowPath = "/c/fakeroomtoken";
+        fakeGetWindowData.windowPath = "/fakeroomtoken";
 
         store.extractTokenInfo(
           new sharedActions.ExtractTokenInfo(fakeGetWindowData));
 
         sinon.assert.calledOnce(dispatcher.dispatch);
         sinon.assert.calledWithExactly(dispatcher.dispatch,
           new sharedActions.FetchServerData({
-            windowType: "outgoing",
+            cryptoKey: null,
+            windowType: "room",
             token: "fakeroomtoken"
           }));
       });
 
+    it("should dispatch a FetchServerData action with a crypto key extracted from the hash", function() {
+      fakeGetWindowData = {
+        windowPath: "/fakeroomtoken",
+        windowHash: "#fakeKey"
+      };
+
+      store.extractTokenInfo(
+        new sharedActions.ExtractTokenInfo(fakeGetWindowData));
+
+      sinon.assert.calledOnce(dispatcher.dispatch);
+      sinon.assert.calledWithExactly(dispatcher.dispatch,
+        new sharedActions.FetchServerData({
+          cryptoKey: "fakeKey",
+          windowType: "room",
+          token: "fakeroomtoken"
+        }));
+    });
   });
 
 });
--- a/browser/components/loop/test/standalone/standaloneRoomViews_test.js
+++ b/browser/components/loop/test/standalone/standaloneRoomViews_test.js
@@ -6,16 +6,17 @@
 
 var expect = chai.expect;
 
 describe("loop.standaloneRoomViews", function() {
   "use strict";
 
   var ROOM_STATES = loop.store.ROOM_STATES;
   var FEEDBACK_STATES = loop.store.FEEDBACK_STATES;
+  var ROOM_INFO_FAILURES = loop.shared.utils.ROOM_INFO_FAILURES;
   var sharedActions = loop.shared.actions;
 
   var sandbox, dispatcher, activeRoomStore, feedbackStore, dispatch;
 
   beforeEach(function() {
     sandbox = sinon.sandbox.create();
     dispatcher = new loop.Dispatcher();
     dispatch = sandbox.stub(dispatcher, "dispatch");
@@ -33,16 +34,54 @@ describe("loop.standaloneRoomViews", fun
     // Prevents audio request errors in the test console.
     sandbox.useFakeXMLHttpRequest();
   });
 
   afterEach(function() {
     sandbox.restore();
   });
 
+  describe("StandaloneRoomContextView", function() {
+    beforeEach(function() {
+      sandbox.stub(navigator.mozL10n, "get").returnsArg(0);
+    });
+
+    function mountTestComponent(props) {
+      return TestUtils.renderIntoDocument(
+        React.createElement(
+          loop.standaloneRoomViews.StandaloneRoomContextView, props));
+    }
+
+    it("should display the room name if no failures are known", function() {
+      var view = mountTestComponent({
+        roomName: "Mike's room"
+      });
+
+      expect(view.getDOMNode().textContent).eql("Mike's room");
+    });
+
+    it("should display an unsupported browser message if crypto is unsupported", function() {
+      var view = mountTestComponent({
+        roomName: "Mark's room",
+        roomInfoFailure: ROOM_INFO_FAILURES.WEB_CRYPTO_UNSUPPORTED
+      });
+
+      expect(view.getDOMNode().textContent).match(/unsupported/);
+    });
+
+    it("should display a general error message for any other failure", function() {
+      var view = mountTestComponent({
+        roomName: "Mark's room",
+        roomInfoFailure: ROOM_INFO_FAILURES.NO_DATA
+      });
+
+      expect(view.getDOMNode().textContent).match(/not_available/);
+    });
+  });
+
   describe("StandaloneRoomView", function() {
     function mountTestComponent() {
       return TestUtils.renderIntoDocument(
         React.createElement(
           loop.standaloneRoomViews.StandaloneRoomView, {
             dispatcher: dispatcher,
             activeRoomStore: activeRoomStore,
             isFirefox: true
--- a/browser/components/loop/test/standalone/webapp_test.js
+++ b/browser/components/loop/test/standalone/webapp_test.js
@@ -66,29 +66,30 @@ describe("loop.webapp", function() {
       sinon.assert.calledOnce(React.render);
       sinon.assert.calledWith(React.render,
         sinon.match(function(value) {
           return TestUtils.isCompositeComponentElement(value,
             loop.webapp.WebappRootView);
       }));
     });
 
-    it("should dispatch a ExtractTokenInfo action with the path",
+    it("should dispatch a ExtractTokenInfo action with the path and hash",
       function() {
         sandbox.stub(loop.shared.utils, "locationData").returns({
-          hash: "",
+          hash: "#fakeKey",
           pathname: "/c/faketoken"
         });
 
       loop.webapp.init();
 
       sinon.assert.calledOnce(loop.Dispatcher.prototype.dispatch);
       sinon.assert.calledWithExactly(loop.Dispatcher.prototype.dispatch,
         new sharedActions.ExtractTokenInfo({
-          windowPath: "/c/faketoken"
+          windowPath: "/c/faketoken",
+          windowHash: "#fakeKey"
         }));
     });
   });
 
   describe("OutgoingConversationView", function() {
     var ocView, conversation, client;
 
     function mountTestComponent(props) {
--- a/browser/components/readinglist/ReadingList.jsm
+++ b/browser/components/readinglist/ReadingList.jsm
@@ -228,41 +228,43 @@ ReadingListImpl.prototype = {
    *        is resolved.
    * @param optsList A variable number of options objects that control the
    *        items that are matched.  See Options Objects.
    * @return Promise<null> Resolved when the enumeration completes *and* the
    *         last promise returned by the callback is resolved.  Rejected with
    *         an Error on error.
    */
   forEachItem: Task.async(function* (callback, ...optsList) {
-    yield this._forEachItem(callback, optsList, STORE_OPTIONS_IGNORE_DELETED);
+    let thisCallback = record => callback(this._itemFromRecord(record));
+    yield this._forEachRecord(thisCallback, optsList, STORE_OPTIONS_IGNORE_DELETED);
   }),
 
   /**
-   * Like forEachItem, but enumerates only previously synced items that are
-   * marked as being locally deleted.
+   * Enumerates the GUIDs for previously synced items that are marked as being
+   * locally deleted.
    */
-  forEachSyncedDeletedItem: Task.async(function* (callback, ...optsList) {
-    yield this._forEachItem(callback, optsList, {
+  forEachSyncedDeletedGUID: Task.async(function* (callback, ...optsList) {
+    let thisCallback = record => callback(record.guid);
+    yield this._forEachRecord(thisCallback, optsList, {
       syncStatus: SYNC_STATUS_DELETED,
     });
   }),
 
   /**
    * See forEachItem.
    *
    * @param storeOptions An options object passed to the store as the "control"
    *        options.
    */
-  _forEachItem: Task.async(function* (callback, optsList, storeOptions) {
+  _forEachRecord: Task.async(function* (callback, optsList, storeOptions) {
     let promiseChain = Promise.resolve();
     yield this._store.forEachItem(record => {
       promiseChain = promiseChain.then(() => {
         return new Promise((resolve, reject) => {
-          let promise = callback(this._itemFromRecord(record));
+          let promise = callback(record);
           if (promise instanceof Promise) {
             return promise.then(resolve, reject);
           }
           resolve();
           return undefined;
         });
       });
     }, optsList, storeOptions);
@@ -312,17 +314,19 @@ ReadingListImpl.prototype = {
       } catch (ex) {
         record.addedBy = SyncUtils.getDefaultDeviceName();
       }
     }
     if (!("syncStatus" in record)) {
       record.syncStatus = SYNC_STATUS_NEW;
     }
 
+    log.debug("addingItem with guid: ${guid}, url: ${url}", record);
     yield this._store.addItem(record);
+    log.trace("added item with guid: ${guid}, url: ${url}", record);
     this._invalidateIterators();
     let item = this._itemFromRecord(record);
     this._callListeners("onItemAdded", item);
     let mm = Cc["@mozilla.org/globalmessagemanager;1"].getService(Ci.nsIMessageListenerManager);
     mm.broadcastAsyncMessage("Reader:Added", item);
     return item;
   }),
 
@@ -340,17 +344,19 @@ ReadingListImpl.prototype = {
    * @return Promise<null> Resolved when the list is updated.  Rejected with an
    *         Error on error.
    */
   updateItem: Task.async(function* (item) {
     if (!item._record.url) {
       throw new Error("The item must have a url");
     }
     this._ensureItemBelongsToList(item);
+    log.debug("updatingItem with guid: ${guid}, url: ${url}", item._record);
     yield this._store.updateItem(item._record);
+    log.trace("finished update of item guid: ${guid}, url: ${url}", item._record);
     this._invalidateIterators();
     this._callListeners("onItemUpdated", item);
   }),
 
   /**
    * Deletes an item from the list.  The item must have a `url`.
    *
    * It's an error to call this for an item that doesn't belong to the list.
@@ -362,33 +368,38 @@ ReadingListImpl.prototype = {
    */
   deleteItem: Task.async(function* (item) {
     this._ensureItemBelongsToList(item);
 
     // If the item is new and therefore hasn't been synced yet, delete it from
     // the store.  Otherwise mark it as deleted but don't actually delete it so
     // that its status can be synced.
     if (item._record.syncStatus == SYNC_STATUS_NEW) {
+      log.debug("deleteItem guid: ${guid}, url: ${url} - item is local so really deleting it", item._record);
       yield this._store.deleteItemByURL(item.url);
     }
     else {
       // To prevent data leakage, only keep the record fields needed to sync
       // the deleted status: guid and syncStatus.
       let newRecord = {};
       for (let prop of ITEM_RECORD_PROPERTIES) {
         newRecord[prop] = null;
       }
       newRecord.guid = item._record.guid;
       newRecord.syncStatus = SYNC_STATUS_DELETED;
-      item._record = newRecord;
-      yield this._store.updateItemByGUID(item._record);
+      log.debug("deleteItem guid: ${guid}, url: ${url} - item has been synced so updating to deleted state", item._record);
+      yield this._store.updateItemByGUID(newRecord);
     }
 
+    log.trace("finished db operation deleting item with guid: ${guid}, url: ${url}", item._record);
     item.list = null;
-    this._itemsByNormalizedURL.delete(item.url);
+    // failing to remove the item from the map points at something bad!
+    if (!this._itemsByNormalizedURL.delete(item.url)) {
+      log.error("Failed to remove item from the map", item);
+    }
     this._invalidateIterators();
     let mm = Cc["@mozilla.org/globalmessagemanager;1"].getService(Ci.nsIMessageListenerManager);
     mm.broadcastAsyncMessage("Reader:Removed", item);
     this._callListeners("onItemDeleted", item);
   }),
 
   /**
    * Finds the first item that matches the given options.
@@ -509,16 +520,19 @@ ReadingListImpl.prototype = {
   /**
    * Returns the ReadingListItem represented by the given record object.  If
    * the item doesn't exist yet, it's created first.
    *
    * @param record A simple object with *normalized* item record properties.
    * @return The ReadingListItem.
    */
   _itemFromRecord(record) {
+    if (!record.url) {
+      throw new Error("record must have a URL");
+    }
     let itemWeakRef = this._itemsByNormalizedURL.get(record.url);
     let item = itemWeakRef ? itemWeakRef.get() : null;
     if (item) {
       item._record = record;
     }
     else {
       item = new ReadingListItem(record);
       item.list = this;
--- a/browser/components/readinglist/Sync.jsm
+++ b/browser/components/readinglist/Sync.jsm
@@ -291,19 +291,19 @@ SyncImpl.prototype = {
    *
    * Uploads deleted synced items.
    */
   _uploadDeletedItems: Task.async(function* () {
     log.debug("Phase 1 part 3: Uploading deleted items");
 
     // Get deleted synced local items.
     let requests = [];
-    yield this.list.forEachSyncedDeletedItem(localItem => {
+    yield this.list.forEachSyncedDeletedGUID(guid => {
       requests.push({
-        path: "/articles/" + localItem.guid,
+        path: "/articles/" + guid,
       });
     });
     if (!requests.length) {
       log.debug("No local deleted synced items to upload");
       return;
     }
 
     // Send the request.
--- a/browser/components/readinglist/sidebar.js
+++ b/browser/components/readinglist/sidebar.js
@@ -113,20 +113,22 @@ let RLSidebar = {
   /**
    * Handle an item being deleted from the ReadingList.
    * @param {ReadingListItem} item - Item that was deleted.
    */
   onItemDeleted(item) {
     log.trace(`onItemDeleted: ${item}`);
 
     let itemNode = this.itemNodesById.get(item.id);
+
+    this.itemNodesById.delete(item.id);
+    this.itemsById.delete(item.id);
+
     itemNode.addEventListener('transitionend', (event) => {
       if (event.propertyName == "max-height") {
-        this.itemNodesById.delete(item.id);
-        this.itemsById.delete(item.id);
         itemNode.remove();
 
         // TODO: ensureListItems doesn't yet cope with needing to add one item.
         //this.ensureListItems();
 
         this.emptyListInfo.hidden = (this.numItems > 0);
       }
     }, false);
--- a/browser/components/readinglist/test/xpcshell/test_ReadingList.js
+++ b/browser/components/readinglist/test/xpcshell/test_ReadingList.js
@@ -4,16 +4,20 @@
 "use strict";
 
 let gDBFile = do_get_profile();
 
 Cu.import("resource:///modules/readinglist/ReadingList.jsm");
 Cu.import("resource:///modules/readinglist/SQLiteStore.jsm");
 Cu.import("resource://gre/modules/Sqlite.jsm");
 Cu.import("resource://gre/modules/Timer.jsm");
+Cu.import("resource://gre/modules/Log.jsm");
+
+Log.repository.getLogger("readinglist.api").level = Log.Level.All;
+Log.repository.getLogger("readinglist.api").addAppender(new Log.DumpAppender());
 
 var gList;
 var gItems;
 
 function run_test() {
   run_next_test();
 }
 
@@ -289,20 +293,20 @@ add_task(function* forEachItem() {
 
 add_task(function* forEachSyncedDeletedItem() {
   let deletedItem = yield gList.addItem({
     guid: "forEachSyncedDeletedItem",
     url: "http://example.com/forEachSyncedDeletedItem",
   });
   deletedItem._record.syncStatus = gList.SyncStatus.SYNCED;
   yield gList.deleteItem(deletedItem);
-  let items = [];
-  yield gList.forEachSyncedDeletedItem(item => items.push(item));
-  Assert.equal(items.length, 1);
-  Assert.equal(items[0].guid, deletedItem.guid);
+  let guids = [];
+  yield gList.forEachSyncedDeletedGUID(guid => guids.push(guid));
+  Assert.equal(guids.length, 1);
+  Assert.equal(guids[0], deletedItem.guid);
 });
 
 add_task(function* forEachItem_promises() {
   // promises resolved immediately
   let items = [];
   yield gList.forEachItem(item => {
     items.push(item);
     return Promise.resolve();
@@ -649,17 +653,17 @@ add_task(function* listeners() {
   items[0].delete();
   listenerItem = yield listenerPromise;
   Assert.ok(listenerItem);
   Assert.ok(listenerItem === items[0]);
   gList.removeListener(listener);
   Assert.equal((yield gList.count()), gItems.length);
 });
 
-// This test deletes items so it should probably run last.
+// This test deletes items so it should probably run last of the 'gItems' tests...
 add_task(function* deleteItem() {
   // delete first item with item.delete()
   let iter = gList.iterator({
     sort: "guid",
   });
   let item = (yield iter.items(1))[0];
   Assert.ok(item);
   item.delete();
@@ -687,16 +691,38 @@ add_task(function* deleteItem() {
   Assert.equal((yield gList.count()), gItems.length - 3);
   items = [];
   yield gList.forEachItem(i => items.push(i), {
     sort: "guid",
   });
   checkItems(items, gItems.slice(3));
 });
 
+// Check that when we delete an item with a GUID it's no longer available as
+// an item
+add_task(function* deletedItemRemovedFromMap() {
+  yield gList.forEachItem(item => item.delete());
+  Assert.equal((yield gList.count()), 0);
+  let map = gList._itemsByNormalizedURL;
+  Assert.equal(gList._itemsByNormalizedURL.size, 0, [for (i of map.keys()) i]);
+  let record = {
+    guid: "test-item",
+    url: "http://localhost",
+    syncStatus: gList.SyncStatus.SYNCED,
+  }
+  let item = yield gList.addItem(record);
+  Assert.equal(map.size, 1);
+  yield item.delete();
+  Assert.equal(gList._itemsByNormalizedURL.size, 0, [for (i of map.keys()) i]);
+
+  // Now enumerate deleted items - should not come back.
+  yield gList.forEachSyncedDeletedGUID(() => {});
+  Assert.equal(gList._itemsByNormalizedURL.size, 0, [for (i of map.keys()) i]);
+});
+
 function checkItems(actualItems, expectedItems) {
   Assert.equal(actualItems.length, expectedItems.length);
   for (let i = 0; i < expectedItems.length; i++) {
     for (let prop in expectedItems[i]._record) {
       Assert.ok(prop in actualItems[i]._record, prop);
       Assert.equal(actualItems[i]._record[prop], expectedItems[i][prop]);
     }
   }
--- a/browser/devtools/animationinspector/test/browser.ini
+++ b/browser/devtools/animationinspector/test/browser.ini
@@ -1,9 +1,10 @@
 [DEFAULT]
+tags = devtools
 subsuite = devtools
 support-files =
   doc_frame_script.js
   doc_simple_animation.html
   head.js
 
 [browser_animation_empty_on_invalid_nodes.js]
 [browser_animation_iterationCount_hidden_by_default.js]
--- a/browser/devtools/animationinspector/test/head.js
+++ b/browser/devtools/animationinspector/test/head.js
@@ -274,17 +274,46 @@ let togglePlayPauseButton = Task.async(f
   // Verify that the button's state is changed immediately, even if it will be
   // changed anyway with the next auto-refresh.
   ok(widget.el.classList.contains(nextState),
     "The button's state was changed in the UI before the request was sent");
 
   yield onClicked;
 
   // Wait for the next sate change event to make sure the state is updated
-  yield widget.player.once(widget.player.AUTO_REFRESH_EVENT);
+  yield waitForStateCondition(widget.player, state => {
+    return state.playState === nextState;
+  }, "after clicking the toggle button");
+});
+
+/**
+ * Wait for a player's auto-refresh events and stop when a condition becomes
+ * truthy.
+ * @param {AnimationPlayerFront} player
+ * @param {Function} conditionCheck Will be called over and over again when the
+ * player state changes, passing the state as argument. This method must return
+ * a truthy value to stop waiting.
+ * @param {String} desc If provided, this will be logged with info(...) every
+ * time the state is refreshed, until the condition passes.
+ * @return {Promise} Resolves when the condition passes.
+ */
+let waitForStateCondition = Task.async(function*(player, conditionCheck, desc="") {
+  if (desc) {
+    desc = "(" + desc + ")";
+  }
+  info("Waiting for a player's auto-refresh event " + desc);
+  let def = promise.defer();
+  player.on(player.AUTO_REFRESH_EVENT, function onNewState() {
+    info("State refreshed, checking condition ... " + desc);
+    if (conditionCheck(player.state)) {
+      player.off(player.AUTO_REFRESH_EVENT, onNewState);
+      def.resolve();
+    }
+  });
+  return def.promise;
 });
 
 /**
  * Get the current playState of an animation player on a given node.
  */
 let getAnimationPlayerState = Task.async(function*(selector, animationIndex=0) {
   let playState = yield executeInContent("Test:GetAnimationPlayerState",
                                          {selector, animationIndex});
--- a/browser/devtools/app-manager/test/browser.ini
+++ b/browser/devtools/app-manager/test/browser.ini
@@ -1,9 +1,10 @@
 [DEFAULT]
+tags = devtools
 skip-if = e10s # Bug ?????? - devtools tests disabled with e10s
 subsuite = devtools
 support-files =
   head.js
   hosted_app.manifest
   manifest.webapp
 
 [browser_manifest_editor.js]
--- a/browser/devtools/app-manager/test/chrome.ini
+++ b/browser/devtools/app-manager/test/chrome.ini
@@ -1,9 +1,10 @@
 [DEFAULT]
+tags = devtools
 skip-if = buildapp == 'b2g'
 support-files =
   hosted_app.manifest
   validator/*
 
 [test_connection_store.html]
 [test_device_store.html]
 [test_projects_store.html]
--- a/browser/devtools/canvasdebugger/test/browser.ini
+++ b/browser/devtools/canvasdebugger/test/browser.ini
@@ -1,9 +1,10 @@
 [DEFAULT]
+tags = devtools
 subsuite = devtools
 support-files =
   doc_raf-begin.html
   doc_settimeout.html
   doc_no-canvas.html
   doc_raf-no-canvas.html
   doc_simple-canvas.html
   doc_simple-canvas-bitmasks.html
--- a/browser/devtools/commandline/test/browser.ini
+++ b/browser/devtools/commandline/test/browser.ini
@@ -1,9 +1,10 @@
 [DEFAULT]
+tags = devtools
 skip-if = e10s # Bug ?????? - devtools tests disabled with e10s
 subsuite = devtools
 support-files =
   head.js
   helpers.js
   mockCommands.js
 
 [browser_cmd_addon.js]
--- a/browser/devtools/debugger/test/browser.ini
+++ b/browser/devtools/debugger/test/browser.ini
@@ -1,9 +1,10 @@
 [DEFAULT]
+tags = devtools
 subsuite = devtools
 support-files =
   addon1.xpi
   addon2.xpi
   addon3.xpi
   addon4.xpi
   addon5.xpi
   code_binary_search.coffee
--- a/browser/devtools/debugger/test/browser_dbg_pretty-print-08.js
+++ b/browser/devtools/debugger/test/browser_dbg_pretty-print-08.js
@@ -16,17 +16,17 @@ function test() {
     gThreadClient = gPanel.panelWin.DebuggerController.activeThread;
 
     findSource();
   });
 }
 
 const BP_LOCATION = {
   line: 5,
-  column: 11
+  // column: 0
 };
 
 function findSource() {
   gThreadClient.getSources(({ error, sources }) => {
     ok(!error, "error should exist");
     sources = sources.filter(s => s.url.contains("code_ugly-3.js"));
     is(sources.length, 1, "sources.length should be 1");
     [gSource] = sources;
--- a/browser/devtools/eyedropper/test/browser.ini
+++ b/browser/devtools/eyedropper/test/browser.ini
@@ -1,9 +1,10 @@
 [DEFAULT]
+tags = devtools
 subsuite = devtools
 support-files =
   color-block.html
   head.js
 
 [browser_eyedropper_basic.js]
 skip-if = os == "win" && debug # bug 963492
 [browser_eyedropper_cmd.js]
--- a/browser/devtools/fontinspector/test/browser.ini
+++ b/browser/devtools/fontinspector/test/browser.ini
@@ -1,9 +1,10 @@
 [DEFAULT]
+tags = devtools
 subsuite = devtools
 support-files =
   browser_fontinspector.html
   test_iframe.html
   ostrich-black.ttf
   ostrich-regular.ttf
   head.js
 
--- a/browser/devtools/framework/test/browser.ini
+++ b/browser/devtools/framework/test/browser.ini
@@ -1,9 +1,10 @@
 [DEFAULT]
+tags = devtools
 subsuite = devtools
 support-files =
   browser_toolbox_options_disable_js.html
   browser_toolbox_options_disable_js_iframe.html
   browser_toolbox_options_disable_cache.sjs
   browser_toolbox_sidebar_tool.xul
   head.js
   helper_disable_cache.js
--- a/browser/devtools/inspector/test/browser.ini
+++ b/browser/devtools/inspector/test/browser.ini
@@ -1,9 +1,10 @@
 [DEFAULT]
+tags = devtools
 subsuite = devtools
 support-files =
   doc_frame_script.js
   doc_inspector_breadcrumbs.html
   doc_inspector_delete-selected-node-01.html
   doc_inspector_delete-selected-node-02.html
   doc_inspector_gcli-inspect-command.html
   doc_inspector_highlight_after_transition.html
--- a/browser/devtools/layoutview/test/browser.ini
+++ b/browser/devtools/layoutview/test/browser.ini
@@ -1,9 +1,10 @@
 [DEFAULT]
+tags = devtools
 skip-if = e10s # Bug ?????? - devtools tests disabled with e10s
 subsuite = devtools
 support-files =
   doc_layoutview_iframe1.html
   doc_layoutview_iframe2.html
   head.js
 
 [browser_layoutview.js]
--- a/browser/devtools/markupview/test/browser.ini
+++ b/browser/devtools/markupview/test/browser.ini
@@ -1,9 +1,10 @@
 [DEFAULT]
+tags = devtools
 subsuite = devtools
 support-files =
   doc_markup_anonymous.html
   doc_markup_dragdrop.html
   doc_markup_dragdrop_autoscroll.html
   doc_markup_edit.html
   doc_markup_events.html
   doc_markup_events_jquery.html
--- a/browser/devtools/netmonitor/test/browser.ini
+++ b/browser/devtools/netmonitor/test/browser.ini
@@ -1,9 +1,10 @@
 [DEFAULT]
+tags = devtools
 subsuite = devtools
 support-files =
   head.js
   html_content-type-test-page.html
   html_content-type-without-cache-test-page.html
   html_custom-get-page.html
   html_single-get-page.html
   html_cyrillic-test-page.html
--- a/browser/devtools/performance/performance-controller.js
+++ b/browser/devtools/performance/performance-controller.js
@@ -55,16 +55,19 @@ devtools.lazyImporter(this, "SideMenuWid
 
 const BRANCH_NAME = "devtools.performance.ui.";
 
 // Events emitted by various objects in the panel.
 const EVENTS = {
   // Fired by the PerformanceController and OptionsView when a pref changes.
   PREF_CHANGED: "Performance:PrefChanged",
 
+  // Fired by the PerformanceController when the devtools theme changes.
+  THEME_CHANGED: "Performance:ThemeChanged",
+
   // Emitted by the PerformanceView when the state (display mode) changes,
   // for example when switching between "empty", "recording" or "recorded".
   // This causes certain panels to be hidden or visible.
   UI_STATE_CHANGED: "Performance:UI:StateChanged",
 
   // Emitted by the PerformanceView on clear button click
   UI_CLEAR_RECORDINGS: "Performance:UI:ClearRecordings",
 
@@ -172,16 +175,17 @@ let PerformanceController = {
     this.startRecording = this.startRecording.bind(this);
     this.stopRecording = this.stopRecording.bind(this);
     this.importRecording = this.importRecording.bind(this);
     this.exportRecording = this.exportRecording.bind(this);
     this.clearRecordings = this.clearRecordings.bind(this);
     this._onTimelineData = this._onTimelineData.bind(this);
     this._onRecordingSelectFromView = this._onRecordingSelectFromView.bind(this);
     this._onPrefChanged = this._onPrefChanged.bind(this);
+    this._onThemeChanged = this._onThemeChanged.bind(this);
 
     // All boolean prefs should be handled via the OptionsView in the
     // ToolbarView, so that they may be accessible via the "gear" menu.
     // Every other pref should be registered here.
     this._nonBooleanPrefs = new ViewHelpers.Prefs("devtools.performance", {
       "hidden-markers": ["Json", "timeline.hidden-markers"],
       "memory-sample-probability": ["Float", "memory.sample-probability"],
       "memory-max-log-length": ["Int", "memory.max-log-length"]
@@ -193,16 +197,17 @@ let PerformanceController = {
     ToolbarView.on(EVENTS.PREF_CHANGED, this._onPrefChanged);
     PerformanceView.on(EVENTS.UI_START_RECORDING, this.startRecording);
     PerformanceView.on(EVENTS.UI_STOP_RECORDING, this.stopRecording);
     PerformanceView.on(EVENTS.UI_IMPORT_RECORDING, this.importRecording);
     PerformanceView.on(EVENTS.UI_CLEAR_RECORDINGS, this.clearRecordings);
     RecordingsView.on(EVENTS.UI_EXPORT_RECORDING, this.exportRecording);
     RecordingsView.on(EVENTS.RECORDING_SELECTED, this._onRecordingSelectFromView);
 
+    gDevTools.on("pref-changed", this._onThemeChanged);
     gFront.on("markers", this._onTimelineData); // timeline markers
     gFront.on("frames", this._onTimelineData); // stack frames
     gFront.on("memory", this._onTimelineData); // memory measurements
     gFront.on("ticks", this._onTimelineData); // framerate
     gFront.on("allocations", this._onTimelineData); // memory allocations
   }),
 
   /**
@@ -215,24 +220,32 @@ let PerformanceController = {
     ToolbarView.off(EVENTS.PREF_CHANGED, this._onPrefChanged);
     PerformanceView.off(EVENTS.UI_START_RECORDING, this.startRecording);
     PerformanceView.off(EVENTS.UI_STOP_RECORDING, this.stopRecording);
     PerformanceView.off(EVENTS.UI_IMPORT_RECORDING, this.importRecording);
     PerformanceView.off(EVENTS.UI_CLEAR_RECORDINGS, this.clearRecordings);
     RecordingsView.off(EVENTS.UI_EXPORT_RECORDING, this.exportRecording);
     RecordingsView.off(EVENTS.RECORDING_SELECTED, this._onRecordingSelectFromView);
 
+    gDevTools.off("pref-changed", this._onThemeChanged);
     gFront.off("markers", this._onTimelineData);
     gFront.off("frames", this._onTimelineData);
     gFront.off("memory", this._onTimelineData);
     gFront.off("ticks", this._onTimelineData);
     gFront.off("allocations", this._onTimelineData);
   },
 
   /**
+   * Returns the current devtools theme.
+   */
+  getTheme: function () {
+    return Services.prefs.getCharPref("devtools.theme");
+  },
+
+  /**
    * Get a boolean preference setting from `prefName` via the underlying
    * OptionsView in the ToolbarView.
    *
    * @param string prefName
    * @return boolean
    */
   getOption: function (prefName) {
     return ToolbarView.optionsView.getPref(prefName);
@@ -409,16 +422,29 @@ let PerformanceController = {
   /**
    * Fired when the ToolbarView fires a PREF_CHANGED event.
    * with the value.
    */
   _onPrefChanged: function (_, prefName, prefValue) {
     this.emit(EVENTS.PREF_CHANGED, prefName, prefValue);
   },
 
+  /*
+   * Called when the developer tools theme changes.
+   */
+  _onThemeChanged: function (_, data) {
+    // Right now, gDevTools only emits `pref-changed` for the theme,
+    // but this could change in the future.
+    if (data.pref !== "devtools.theme") {
+      return;
+    }
+
+    this.emit(EVENTS.THEME_CHANGED, data.newValue);
+  },
+
   toString: () => "[object PerformanceController]"
 };
 
 /**
  * Convenient way of emitting events from the controller.
  */
 EventEmitter.decorate(PerformanceController);
 
--- a/browser/devtools/performance/test/browser.ini
+++ b/browser/devtools/performance/test/browser.ini
@@ -1,9 +1,10 @@
 [DEFAULT]
+tags = devtools
 skip-if = e10s # Handle in Bug 1077464 for profiler
 subsuite = devtools
 support-files =
   doc_simple-test.html
   head.js
 
 # Commented out tests are profiler tests
 # that need to be moved over to performance tool
@@ -76,16 +77,17 @@ support-files =
 [browser_perf_recordings-io-02.js]
 [browser_perf_recordings-io-03.js]
 [browser_perf_recordings-io-04.js]
 [browser_perf-range-changed-render.js]
 [browser_perf-recording-selected-01.js]
 [browser_perf-recording-selected-02.js]
 [browser_perf-recording-selected-03.js]
 [browser_perf-recording-selected-04.js]
+[browser_perf-theme-toggle-01.js]
 [browser_profiler_categories.js]
 [browser_profiler_content-check.js]
 [browser_profiler_tree-abstract-01.js]
 [browser_profiler_tree-abstract-02.js]
 [browser_profiler_tree-abstract-03.js]
 [browser_profiler_tree-abstract-04.js]
 [browser_profiler_tree-frame-node.js]
 [browser_profiler_tree-model-01.js]
new file mode 100644
--- /dev/null
+++ b/browser/devtools/performance/test/browser_perf-theme-toggle-01.js
@@ -0,0 +1,86 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+/**
+ * Tests if the markers and memory overviews render with the correct
+ * theme on load, and rerenders when changed.
+ */
+
+const LIGHT_BG = "#fcfcfc";
+const DARK_BG = "#14171a";
+
+setTheme("dark");
+Services.prefs.setBoolPref(MEMORY_PREF, false);
+
+function spawnTest () {
+  let { panel } = yield initPerformance(SIMPLE_URL);
+  let { EVENTS, $, OverviewView, document: doc } = panel.panelWin;
+
+  yield startRecording(panel);
+  is(OverviewView.markersOverview.backgroundColor, DARK_BG,
+    "correct theme on load for markers.");
+  yield stopRecording(panel);
+
+  let refreshed = once(OverviewView.markersOverview, "refresh");
+  setTheme("light");
+  yield refreshed;
+
+  ok(true, "markers were rerendered after theme change.");
+  is(OverviewView.markersOverview.backgroundColor, LIGHT_BG,
+    "correct theme on after toggle for markers.");
+
+  // reset back to dark
+  refreshed = once(OverviewView.markersOverview, "refresh");
+  setTheme("dark");
+  yield refreshed;
+
+  info("Testing with memory overview");
+
+  Services.prefs.setBoolPref(MEMORY_PREF, true);
+
+  yield startRecording(panel);
+  is(OverviewView.memoryOverview.backgroundColor, DARK_BG,
+    "correct theme on load for memory.");
+  yield stopRecording(panel);
+
+  refreshed = Promise.all([
+    once(OverviewView.markersOverview, "refresh"),
+    once(OverviewView.memoryOverview, "refresh"),
+  ]);
+  setTheme("light");
+  yield refreshed;
+
+  ok(true, "Both memory and markers were rerendered after theme change.");
+  is(OverviewView.markersOverview.backgroundColor, LIGHT_BG,
+    "correct theme on after toggle for markers.");
+  is(OverviewView.memoryOverview.backgroundColor, LIGHT_BG,
+    "correct theme on after toggle for memory.");
+
+  refreshed = Promise.all([
+    once(OverviewView.markersOverview, "refresh"),
+    once(OverviewView.memoryOverview, "refresh"),
+  ]);
+
+  // Set theme back to light
+  setTheme("light");
+  yield refreshed;
+
+  yield teardown(panel);
+  finish();
+}
+
+/**
+ * Mimics selecting the theme selector in the toolbox;
+ * sets the preference and emits an event on gDevTools to trigger
+ * the themeing.
+ */
+function setTheme (newTheme) {
+  let oldTheme = Services.prefs.getCharPref("devtools.theme");
+  info("Setting `devtools.theme` to \"" + newTheme + "\"");
+  Services.prefs.setCharPref("devtools.theme", newTheme);
+  gDevTools.emit("pref-changed", {
+    pref: "devtools.theme",
+    newValue: newTheme,
+    oldValue: oldTheme
+  });
+}
--- a/browser/devtools/performance/views/overview.js
+++ b/browser/devtools/performance/views/overview.js
@@ -32,23 +32,25 @@ let OverviewView = {
     this._onRecordingWillStart = this._onRecordingWillStart.bind(this);
     this._onRecordingStarted = this._onRecordingStarted.bind(this);
     this._onRecordingWillStop = this._onRecordingWillStop.bind(this);
     this._onRecordingStopped = this._onRecordingStopped.bind(this);
     this._onRecordingSelected = this._onRecordingSelected.bind(this);
     this._onRecordingTick = this._onRecordingTick.bind(this);
     this._onGraphSelecting = this._onGraphSelecting.bind(this);
     this._onPrefChanged = this._onPrefChanged.bind(this);
+    this._onThemeChanged = this._onThemeChanged.bind(this);
 
     // Toggle the initial visibility of memory and framerate graph containers
     // based off of prefs.
     $("#memory-overview").hidden = !PerformanceController.getOption("enable-memory");
     $("#time-framerate").hidden = !PerformanceController.getOption("enable-framerate");
 
     PerformanceController.on(EVENTS.PREF_CHANGED, this._onPrefChanged);
+    PerformanceController.on(EVENTS.THEME_CHANGED, this._onThemeChanged);
     PerformanceController.on(EVENTS.RECORDING_WILL_START, this._onRecordingWillStart);
     PerformanceController.on(EVENTS.RECORDING_STARTED, this._onRecordingStarted);
     PerformanceController.on(EVENTS.RECORDING_WILL_STOP, this._onRecordingWillStop);
     PerformanceController.on(EVENTS.RECORDING_STOPPED, this._onRecordingStopped);
     PerformanceController.on(EVENTS.RECORDING_SELECTED, this._onRecordingSelected);
   },
 
   /**
@@ -61,16 +63,17 @@ let OverviewView = {
     if (this.memoryOverview) {
       yield this.memoryOverview.destroy();
     }
     if (this.framerateGraph) {
       yield this.framerateGraph.destroy();
     }
 
     PerformanceController.off(EVENTS.PREF_CHANGED, this._onPrefChanged);
+    PerformanceController.off(EVENTS.THEME_CHANGED, this._onThemeChanged);
     PerformanceController.off(EVENTS.RECORDING_WILL_START, this._onRecordingWillStart);
     PerformanceController.off(EVENTS.RECORDING_STARTED, this._onRecordingStarted);
     PerformanceController.off(EVENTS.RECORDING_WILL_STOP, this._onRecordingWillStop);
     PerformanceController.off(EVENTS.RECORDING_STOPPED, this._onRecordingStopped);
     PerformanceController.off(EVENTS.RECORDING_SELECTED, this._onRecordingSelected);
   }),
 
   /**
@@ -88,16 +91,33 @@ let OverviewView = {
    *
    * @return boolean
    */
   isDisabled: function () {
     return this._disabled;
   },
 
   /**
+   * Sets the theme for the markers overview and memory overview.
+   */
+  setTheme: function (options={}) {
+    let theme = options.theme || PerformanceController.getTheme();
+
+    if (this.markersOverview) {
+      this.markersOverview.setTheme(theme);
+      this.markersOverview.refresh({ force: options.redraw });
+    }
+
+    if (this.memoryOverview) {
+      this.memoryOverview.setTheme(theme);
+      this.memoryOverview.refresh({ force: options.redraw });
+    }
+  },
+
+  /**
    * Sets the time interval selection for all graphs in this overview.
    *
    * @param object interval
    *        The { startTime, endTime }, in milliseconds.
    */
   setTimeInterval: function(interval, options = {}) {
     let recording = PerformanceController.getCurrentRecording();
     if (recording == null) {
@@ -147,16 +167,17 @@ let OverviewView = {
     }
     let blueprint = PerformanceController.getTimelineBlueprint();
     this.markersOverview = new MarkersOverview($("#markers-overview"), blueprint);
     this.markersOverview.headerHeight = MARKERS_GRAPH_HEADER_HEIGHT;
     this.markersOverview.rowHeight = MARKERS_GRAPH_ROW_HEIGHT;
     this.markersOverview.groupPadding = MARKERS_GROUP_VERTICAL_PADDING;
     this.markersOverview.on("selecting", this._onGraphSelecting);
     yield this.markersOverview.ready();
+    this.setTheme();
     return true;
   }),
 
   /**
    * Sets up the memory overview graph, if allowed and needed.
    *
    * @return object
    *         A promise resolved to `true` if the graph was initialized and is
@@ -168,16 +189,17 @@ let OverviewView = {
     }
     if (this.memoryOverview) {
       yield this.memoryOverview.ready();
       return true;
     }
     this.memoryOverview = new MemoryOverview($("#memory-overview"));
     this.memoryOverview.fixedHeight = MEMORY_GRAPH_HEIGHT;
     yield this.memoryOverview.ready();
+    this.setTheme();
 
     CanvasGraphUtils.linkAnimation(this.markersOverview, this.memoryOverview);
     CanvasGraphUtils.linkSelection(this.markersOverview, this.memoryOverview);
     return true;
   }),
 
   /**
    * Sets up the framerate graph, if allowed and needed.
@@ -364,13 +386,20 @@ let OverviewView = {
           this.markersOverview.setBlueprint(blueprint);
           this.markersOverview.refresh({ force: true });
         }
         break;
       }
     }
   }),
 
+  /**
+   * Called when `devtools.theme` changes.
+   */
+  _onThemeChanged: function (_, theme) {
+    this.setTheme({ theme, redraw: true });
+  },
+
   toString: () => "[object OverviewView]"
 };
 
 // Decorates the OverviewView as an EventEmitter
 EventEmitter.decorate(OverviewView);
--- a/browser/devtools/profiler/test/browser.ini
+++ b/browser/devtools/profiler/test/browser.ini
@@ -1,9 +1,10 @@
 [DEFAULT]
+tags = devtools
 subsuite = devtools
 support-files =
   doc_simple-test.html
   head.js
 
 [browser_profiler_aaa_run_first_leaktest.js]
 [browser_profiler_console-record-01.js]
 skip-if = true # Bug 1047124
--- a/browser/devtools/projecteditor/test/browser.ini
+++ b/browser/devtools/projecteditor/test/browser.ini
@@ -1,9 +1,10 @@
 [DEFAULT]
+tags = devtools
 subsuite = devtools
 support-files =
   head.js
   helper_homepage.html
   helper_edits.js
 
 [browser_projecteditor_app_options.js]
 skip-if = buildapp == 'mulet'
--- a/browser/devtools/responsivedesign/test/browser.ini
+++ b/browser/devtools/responsivedesign/test/browser.ini
@@ -1,9 +1,10 @@
 [DEFAULT]
+tags = devtools
 subsuite = devtools
 support-files =
   head.js
   touch.html
 
 [browser_responsive_cmd.js]
 [browser_responsivecomputedview.js]
 skip-if = e10s # Bug ??????
--- a/browser/devtools/scratchpad/test/browser.ini
+++ b/browser/devtools/scratchpad/test/browser.ini
@@ -1,9 +1,10 @@
 [DEFAULT]
+tags = devtools
 subsuite = devtools
 support-files = head.js
 
 [browser_scratchpad_autocomplete.js]
 [browser_scratchpad_browser_last_window_closing.js]
 [browser_scratchpad_reset_undo.js]
 [browser_scratchpad_display_outputs_errors.js]
 [browser_scratchpad_eval_func.js]
--- a/browser/devtools/shadereditor/test/browser.ini
+++ b/browser/devtools/shadereditor/test/browser.ini
@@ -1,9 +1,10 @@
 [DEFAULT]
+tags = devtools
 subsuite = devtools
 support-files =
   doc_blended-geometry.html
   doc_multiple-contexts.html
   doc_overlapping-geometry.html
   doc_shader-order.html
   doc_simple-canvas.html
   head.js
--- a/browser/devtools/shared/test/browser.ini
+++ b/browser/devtools/shared/test/browser.ini
@@ -1,9 +1,10 @@
 [DEFAULT]
+tags = devtools
 subsuite = devtools
 support-files =
   browser_layoutHelpers.html
   browser_layoutHelpers-getBoxQuads.html
   browser_layoutHelpers_iframe.html
   browser_templater_basic.html
   browser_toolbar_basic.html
   browser_toolbar_webconsole_errors_count.html
--- a/browser/devtools/shared/test/unit/xpcshell.ini
+++ b/browser/devtools/shared/test/unit/xpcshell.ini
@@ -1,10 +1,11 @@
 [DEFAULT]
+tags = devtools
 head =
 tail =
 firefox-appdir = browser
 skip-if = toolkit == 'android' || toolkit == 'gonk'
 
 [test_bezierCanvas.js]
 [test_cubicBezier.js]
 [test_undoStack.js]
-[test_VariablesView_getString_promise.js]
\ No newline at end of file
+[test_VariablesView_getString_promise.js]
--- a/browser/devtools/shared/timeline/memory-overview.js
+++ b/browser/devtools/shared/timeline/memory-overview.js
@@ -64,17 +64,17 @@ MemoryOverview.prototype = Heritage.exte
   /**
    * Sets the theme via `theme` to either "light" or "dark",
    * and updates the internal styling to match. Requires a redraw
    * to see the effects.
    */
   setTheme: function (theme) {
     theme = theme || "light";
     this.backgroundColor = getColor("body-background", theme);
-    this.backgroundGradientStart = setAlpha(getColor("highlight-blue", theme), 0.1);
-    this.backgroundGradientEnd = setAlpha(getColor("highlight-blue", theme), 0);
+    this.backgroundGradientStart = setAlpha(getColor("highlight-blue", theme), 0.2);
+    this.backgroundGradientEnd = setAlpha(getColor("highlight-blue", theme), 0.05);
     this.strokeColor = getColor("highlight-blue", theme);
     this.selectionBackgroundColor = setAlpha(getColor("selection-background", theme), 0.25);
     this.selectionStripesColor = "rgba(255, 255, 255, 0.1)";
   }
 });
 
 exports.MemoryOverview = MemoryOverview;
--- a/browser/devtools/sourceeditor/test/browser.ini
+++ b/browser/devtools/sourceeditor/test/browser.ini
@@ -1,9 +1,10 @@
 [DEFAULT]
+tags = devtools
 subsuite = devtools
 support-files =
   cm_comment_test.js
   cm_doc_test.js
   cm_driver.js
   cm_emacs_test.js
   cm_mode_test.css
   cm_mode_test.js
--- a/browser/devtools/storage/test/browser.ini
+++ b/browser/devtools/storage/test/browser.ini
@@ -1,9 +1,10 @@
 [DEFAULT]
+tags = devtools
 # Bug 1049888 - storage actors do not work in e10s for now
 # Bug 1105803 - permafailing on debug release builds since devedition landed
 skip-if = e10s || debug
 subsuite = devtools
 support-files =
   storage-complex-values.html
   storage-listings.html
   storage-secured-iframe.html
--- a/browser/devtools/styleeditor/test/browser.ini
+++ b/browser/devtools/styleeditor/test/browser.ini
@@ -1,9 +1,10 @@
 [DEFAULT]
+tags = devtools
 subsuite = devtools
 support-files =
   autocomplete.html
   browser_styleeditor_cmd_edit.html
   four.html
   head.js
   import.css
   import.html
--- a/browser/devtools/styleinspector/test/browser.ini
+++ b/browser/devtools/styleinspector/test/browser.ini
@@ -1,9 +1,10 @@
 [DEFAULT]
+tags = devtools
 subsuite = devtools
 support-files =
   doc_content_stylesheet.html
   doc_content_stylesheet.xul
   doc_content_stylesheet_imported.css
   doc_content_stylesheet_imported2.css
   doc_content_stylesheet_linked.css
   doc_content_stylesheet_script.css
--- a/browser/devtools/styleinspector/test/unit/xpcshell.ini
+++ b/browser/devtools/styleinspector/test/unit/xpcshell.ini
@@ -1,8 +1,9 @@
 [DEFAULT]
+tags = devtools
 head =
 tail =
 firefox-appdir = browser
 skip-if = toolkit == 'android' || toolkit == 'gonk'
 
 [test_parseDeclarations.js]
 [test_parseSingleValue.js]
--- a/browser/devtools/tilt/test/browser.ini
+++ b/browser/devtools/tilt/test/browser.ini
@@ -1,9 +1,10 @@
 [DEFAULT]
+tags = devtools
 skip-if = e10s # Bug 1086492 - Disable tilt for e10s
                # Bug 937166 - Make tilt work in E10S mode
 subsuite = devtools
 support-files = head.js
 
 [browser_tilt_01_lazy_getter.js]
 [browser_tilt_02_notifications-seq.js]
 [browser_tilt_02_notifications-tabs.js]
--- a/browser/devtools/timeline/test/browser.ini
+++ b/browser/devtools/timeline/test/browser.ini
@@ -1,9 +1,10 @@
 [DEFAULT]
+tags = devtools
 subsuite = devtools
 support-files =
   doc_simple-test.html
   head.js
 
 [browser_timeline_aaa_run_first_leaktest.js]
 [browser_timeline_overview-initial-selection-01.js]
 [browser_timeline_overview-initial-selection-02.js]
--- a/browser/devtools/webaudioeditor/test/browser.ini
+++ b/browser/devtools/webaudioeditor/test/browser.ini
@@ -1,9 +1,10 @@
 [DEFAULT]
+tags = devtools
 subsuite = devtools
 support-files =
   doc_simple-context.html
   doc_complex-context.html
   doc_simple-node-creation.html
   doc_buffer-and-array.html
   doc_media-node-creation.html
   doc_destroy-nodes.html
--- a/browser/devtools/webconsole/test/browser.ini
+++ b/browser/devtools/webconsole/test/browser.ini
@@ -1,9 +1,10 @@
 [DEFAULT]
+tags = devtools
 subsuite = devtools
 support-files =
   head.js
   test-bug-585956-console-trace.html
   test-bug-593003-iframe-wrong-hud-iframe.html
   test-bug-593003-iframe-wrong-hud.html
   test-bug-595934-canvas-css.html
   test-bug-595934-canvas-css.js
--- a/browser/devtools/webide/test/browser.ini
+++ b/browser/devtools/webide/test/browser.ini
@@ -1,9 +1,10 @@
 [DEFAULT]
+tags = devtools
 subsuite = devtools
 support-files =
   addons/simulators.json
   doc_tabs.html
   head.js
   templates.json
 
 [browser_tabs.js]
--- a/browser/devtools/webide/test/chrome.ini
+++ b/browser/devtools/webide/test/chrome.ini
@@ -1,9 +1,10 @@
 [DEFAULT]
+tags = devtools
 skip-if = buildapp == 'b2g'
 support-files =
   app/index.html
   app/manifest.webapp
   app.zip
   addons/simulators.json
   addons/fxos_1_0_simulator-linux.xpi
   addons/fxos_1_0_simulator-linux64.xpi
--- a/browser/devtools/webide/test/sidebars/browser.ini
+++ b/browser/devtools/webide/test/sidebars/browser.ini
@@ -1,4 +1,5 @@
 [DEFAULT]
+tags = devtools
 subsuite = devtools
 support-files =
   ../head.js
--- a/browser/devtools/webide/test/sidebars/chrome.ini
+++ b/browser/devtools/webide/test/sidebars/chrome.ini
@@ -1,8 +1,9 @@
 [DEFAULT]
+tags = devtools
 support-files =
   ../app/index.html
   ../app/manifest.webapp
   ../head.js
 
 [test_duplicate_import.html]
 [test_import.html]
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -175,17 +175,16 @@
 @RESPATH@/components/browser-element.xpt
 @RESPATH@/browser/components/browsercompsbase.xpt
 @RESPATH@/browser/components/browser-feeds.xpt
 @RESPATH@/browser/components/browsermodules.manifest
 @RESPATH@/components/caps.xpt
 @RESPATH@/components/chrome.xpt
 @RESPATH@/components/commandhandler.xpt
 @RESPATH@/components/commandlines.xpt
-@RESPATH@/components/compartments.xpt
 @RESPATH@/components/composer.xpt
 @RESPATH@/components/content_events.xpt
 @RESPATH@/components/content_html.xpt
 @RESPATH@/components/content_geckomediaplugins.xpt
 #ifdef MOZ_WEBRTC
 @RESPATH@/components/content_webrtc.xpt
 #endif
 @RESPATH@/components/content_xslt.xpt
@@ -323,16 +322,17 @@
 @RESPATH@/components/shistory.xpt
 @RESPATH@/components/spellchecker.xpt
 @RESPATH@/components/storage.xpt
 @RESPATH@/components/toolkit_asyncshutdown.xpt
 @RESPATH@/components/toolkit_filewatcher.xpt
 @RESPATH@/components/toolkit_finalizationwitness.xpt
 @RESPATH@/components/toolkit_formautofill.xpt
 @RESPATH@/components/toolkit_osfile.xpt
+@RESPATH@/components/toolkit_perfmonitoring.xpt
 @RESPATH@/components/toolkit_xulstore.xpt
 @RESPATH@/components/toolkitprofile.xpt
 #ifdef MOZ_ENABLE_XREMOTE
 @RESPATH@/components/toolkitremote.xpt
 #endif
 @RESPATH@/components/txtsvc.xpt
 @RESPATH@/components/txmgr.xpt
 @RESPATH@/components/uconv.xpt
--- a/browser/themes/shared/devtools/widgets.inc.css
+++ b/browser/themes/shared/devtools/widgets.inc.css
@@ -904,17 +904,17 @@
 }
 
 .line-graph-widget-gutter-line[type=average] {
   border-color: #d97e00;
 }
 
 .line-graph-widget-tooltip {
   position: absolute;
-  background: rgba(255,255,255,0.75);
+  background: rgba(255,255,255,0.9);
   border-radius: 2px;
   line-height: 15px;
   -moz-padding-start: 6px;
   -moz-padding-end: 6px;
   transform: translateY(-50%);
   font-size: 80%;
   z-index: 1;
   pointer-events: none;
--- a/docshell/base/nsAboutRedirector.cpp
+++ b/docshell/base/nsAboutRedirector.cpp
@@ -70,17 +70,17 @@ static RedirEntry kRedirMap[] = {
       nsIAboutModule::ALLOW_SCRIPT |
       nsIAboutModule::HIDE_FROM_ABOUTABOUT
   },
   {
     "memory", "chrome://global/content/aboutMemory.xhtml",
     nsIAboutModule::ALLOW_SCRIPT
   },
   {
-    "compartments", "chrome://global/content/aboutCompartments.xhtml",
+    "performance", "chrome://global/content/aboutPerformance.xhtml",
     nsIAboutModule::ALLOW_SCRIPT
   },
   {
     "addons", "chrome://mozapps/content/extensions/extensions.xul",
     nsIAboutModule::ALLOW_SCRIPT
   },
   {
     "newaddon", "chrome://mozapps/content/extensions/newaddon.xul",
--- a/docshell/build/nsDocShellModule.cpp
+++ b/docshell/build/nsDocShellModule.cpp
@@ -161,19 +161,18 @@ const mozilla::Module::ContractIDEntry k
 #endif
   { NS_ABOUT_MODULE_CONTRACTID_PREFIX "credits", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
   { NS_ABOUT_MODULE_CONTRACTID_PREFIX "plugins", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
   { NS_ABOUT_MODULE_CONTRACTID_PREFIX "mozilla", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
   { NS_ABOUT_MODULE_CONTRACTID_PREFIX "logo", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
   { NS_ABOUT_MODULE_CONTRACTID_PREFIX "buildconfig", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
   { NS_ABOUT_MODULE_CONTRACTID_PREFIX "license", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
   { NS_ABOUT_MODULE_CONTRACTID_PREFIX "neterror", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
-  { NS_ABOUT_MODULE_CONTRACTID_PREFIX "compartments", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
   { NS_ABOUT_MODULE_CONTRACTID_PREFIX "memory", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
-  { NS_ABOUT_MODULE_CONTRACTID_PREFIX "compartments", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
+  { NS_ABOUT_MODULE_CONTRACTID_PREFIX "performance", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
   { NS_ABOUT_MODULE_CONTRACTID_PREFIX "addons", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
   { NS_ABOUT_MODULE_CONTRACTID_PREFIX "newaddon", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
   { NS_ABOUT_MODULE_CONTRACTID_PREFIX "support", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
   { NS_ABOUT_MODULE_CONTRACTID_PREFIX "telemetry", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
   { NS_ABOUT_MODULE_CONTRACTID_PREFIX "networking", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
   { NS_ABOUT_MODULE_CONTRACTID_PREFIX "webrtc", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
   { NS_ABOUT_MODULE_CONTRACTID_PREFIX "srcdoc", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
   { NS_URI_LOADER_CONTRACTID, &kNS_URI_LOADER_CID },
--- a/dom/alarm/AlarmsManager.js
+++ b/dom/alarm/AlarmsManager.js
@@ -1,30 +1,38 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
 /* static functions */
 const DEBUG = false;
+const REQUEST_CPU_LOCK_TIMEOUT = 10 * 1000; // 10 seconds.
 
 function debug(aStr) {
   if (DEBUG)
     dump("AlarmsManager: " + aStr + "\n");
 }
 
 const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/DOMRequestHelper.jsm");
 
+XPCOMUtils.defineLazyServiceGetter(this, "gPowerManagerService",
+                                   "@mozilla.org/power/powermanagerservice;1",
+                                   "nsIPowerManagerService");
+
 function AlarmsManager() {
   debug("Constructor");
+
+  // A <requestId, {cpuLock, timer}> map.
+  this._cpuLockDict = new Map();
 }
 
 AlarmsManager.prototype = {
   __proto__: DOMRequestIpcHelper.prototype,
 
   contractID : "@mozilla.org/alarmsManager;1",
 
   classID : Components.ID("{fea1e884-9b05-11e1-9b64-87a7016c3860}"),
@@ -66,18 +74,20 @@ AlarmsManager.prototype = {
       // Run JSON.stringify() in the sand box with the principal of the calling
       // web page to ensure no cross-origin object is involved. A "Permission
       // Denied" error will be thrown in case of privilege violation.
       let sandbox = new Cu.Sandbox(Cu.getWebIDLCallerPrincipal());
       sandbox.data = aData;
       data = JSON.parse(Cu.evalInSandbox("JSON.stringify(data)", sandbox));
     }
     let request = this.createRequest();
+    let requestId = this.getRequestId(request);
+    this._lockCpuForRequest(requestId);
     this._cpmm.sendAsyncMessage("AlarmsManager:Add",
-                                { requestId: this.getRequestId(request),
+                                { requestId: requestId,
                                   date: aDate,
                                   ignoreTimezone: isIgnoreTimezone,
                                   data: data,
                                   pageURL: this._pageURL,
                                   manifestURL: this._manifestURL });
     return request;
   },
 
@@ -106,16 +116,17 @@ AlarmsManager.prototype = {
 
     if (!request) {
       debug("No request stored! " + json.requestId);
       return;
     }
 
     switch (aMessage.name) {
       case "AlarmsManager:Add:Return:OK":
+        this._unlockCpuForRequest(json.requestId);
         Services.DOMRequest.fireSuccess(request, json.id);
         break;
 
       case "AlarmsManager:GetAll:Return:OK":
         // We don't need to expose everything to the web content.
         let alarms = [];
         json.alarms.forEach(function trimAlarmInfo(aAlarm) {
           let alarm = { "id": aAlarm.id,
@@ -126,16 +137,17 @@ AlarmsManager.prototype = {
           alarms.push(alarm);
         });
 
         Services.DOMRequest.fireSuccess(request,
                                         Cu.cloneInto(alarms, this._window));
         break;
 
       case "AlarmsManager:Add:Return:KO":
+        this._unlockCpuForRequest(json.requestId);
         Services.DOMRequest.fireError(request, json.errorMsg);
         break;
 
       case "AlarmsManager:GetAll:Return:KO":
         Services.DOMRequest.fireError(request, json.errorMsg);
         break;
 
       default:
@@ -167,11 +179,49 @@ AlarmsManager.prototype = {
     this._manifestURL = appsService.getManifestURLByLocalId(principal.appId);
     this._window = aWindow;
   },
 
   // Called from DOMRequestIpcHelper.
   uninit: function uninit() {
     debug("uninit()");
   },
+
+  _lockCpuForRequest: function (aRequestId) {
+    if (this._cpuLockDict.has(aRequestId)) {
+      debug('Cpu wakelock for request ' + aRequestId + ' has been acquired. ' +
+            'You may call this function repeatedly or requestId is collision.');
+      return;
+    }
+
+    // Acquire a lock for given request and save for lookup lately.
+    debug('Acquire cpu lock for request ' + aRequestId);
+    let cpuLockInfo = {
+      cpuLock: gPowerManagerService.newWakeLock("cpu"),
+      timer: Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer)
+    };
+    this._cpuLockDict.set(aRequestId, cpuLockInfo);
+
+    // Start a timer to prevent from non-responding request.
+    cpuLockInfo.timer.initWithCallback(() => {
+      debug('Request timeout! Release the cpu lock');
+      this._unlockCpuForRequest(aRequestId);
+    }, REQUEST_CPU_LOCK_TIMEOUT, Ci.nsITimer.TYPE_ONE_SHOT);
+  },
+
+  _unlockCpuForRequest: function(aRequestId) {
+    let cpuLockInfo = this._cpuLockDict.get(aRequestId);
+    if (!cpuLockInfo) {
+      debug('The cpu lock for requestId ' + aRequestId + ' is either invalid ' +
+            'or has been released.');
+      return;
+    }
+
+    // Release the cpu lock and cancel the timer.
+    debug('Release the cpu lock for ' + aRequestId);
+    cpuLockInfo.cpuLock.unlock();
+    cpuLockInfo.timer.cancel();
+    this._cpuLockDict.delete(aRequestId);
+  },
+
 }
 
 this.NSGetFactory = XPCOMUtils.generateNSGetFactory([AlarmsManager])
--- a/dom/base/nsFrameLoader.cpp
+++ b/dom/base/nsFrameLoader.cpp
@@ -879,18 +879,17 @@ nsFrameLoader::ShowRemoteFrame(const Scr
                           "remote-browser-shown", nullptr);
     }
   } else {
     nsIntRect dimensions;
     NS_ENSURE_SUCCESS(GetWindowDimensions(dimensions), false);
 
     // Don't show remote iframe if we are waiting for the completion of reflow.
     if (!aFrame || !(aFrame->GetStateBits() & NS_FRAME_FIRST_REFLOW)) {
-      nsIntPoint chromeDisp = aFrame->GetChromeDisplacement();
-      mRemoteBrowser->UpdateDimensions(dimensions, size, chromeDisp);
+      mRemoteBrowser->UpdateDimensions(dimensions, size);
     }
   }
 
   return true;
 }
 
 void
 nsFrameLoader::Hide()
@@ -1378,16 +1377,22 @@ nsFrameLoader::StartDestroy()
   // references are dropped in DestroyComplete.
   if (mChildMessageManager || mRemoteBrowser) {
     mOwnerContentStrong = mOwnerContent;
     if (mRemoteBrowser) {
       mRemoteBrowser->CacheFrameLoader(this);
     }
   }
 
+  // If the TabParent has installed any event listeners on the window, this is
+  // its last chance to remove them while we're still in the document.
+  if (mRemoteBrowser) {
+    mRemoteBrowser->RemoveWindowListeners();
+  }
+
   nsCOMPtr<nsIDocument> doc;
   bool dynamicSubframeRemoval = false;
   if (mOwnerContent) {
     doc = mOwnerContent->OwnerDoc();
     dynamicSubframeRemoval = !mIsTopLevelContent && !doc->InUnlinkOrDeletion();
     doc->SetSubDocumentFor(mOwnerContent, nullptr);
 
     SetOwnerContent(nullptr);
@@ -2053,18 +2058,17 @@ nsFrameLoader::GetWindowDimensions(nsInt
 NS_IMETHODIMP
 nsFrameLoader::UpdatePositionAndSize(nsSubDocumentFrame *aIFrame)
 {
   if (mRemoteFrame) {
     if (mRemoteBrowser) {
       ScreenIntSize size = aIFrame->GetSubdocumentSize();
       nsIntRect dimensions;
       NS_ENSURE_SUCCESS(GetWindowDimensions(dimensions), NS_ERROR_FAILURE);
-      nsIntPoint chromeDisp = aIFrame->GetChromeDisplacement();
-      mRemoteBrowser->UpdateDimensions(dimensions, size, chromeDisp);
+      mRemoteBrowser->UpdateDimensions(dimensions, size);
     }
     return NS_OK;
   }
   UpdateBaseWindowPositionAndSize(aIFrame);
   return NS_OK;
 }
 
 void
--- a/dom/base/nsFrameLoader.h
+++ b/dom/base/nsFrameLoader.h
@@ -224,16 +224,19 @@ public:
    */
   void ApplySandboxFlags(uint32_t sandboxFlags);
 
   void GetURL(nsString& aURL);
 
   void ActivateUpdateHitRegion();
   void DeactivateUpdateHitRegion();
 
+  // Properly retrieves documentSize of any subdocument type.
+  nsresult GetWindowDimensions(nsIntRect& aRect);
+
 private:
 
   void SetOwnerContent(mozilla::dom::Element* aContent);
 
   bool ShouldUseRemoteProcess();
 
   /**
    * Is this a frameloader for a bona fide <iframe mozbrowser> or
@@ -279,19 +282,16 @@ private:
 
   /**
    * If we are an IPC frame, set mRemoteFrame. Otherwise, create and
    * initialize mDocShell.
    */
   nsresult MaybeCreateDocShell();
   nsresult EnsureMessageManager();
 
-  // Properly retrieves documentSize of any subdocument type.
-  nsresult GetWindowDimensions(nsIntRect& aRect);
-
   // Updates the subdocument position and size. This gets called only
   // when we have our own in-process DocShell.
   void UpdateBaseWindowPositionAndSize(nsSubDocumentFrame *aIFrame);
   nsresult CheckURILoad(nsIURI* aURI);
   void FireErrorEvent();
   nsresult ReallyStartLoadingInternal();
 
   // Return true if remote browser created; nothing else to do
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -1260,25 +1260,16 @@ DOMInterfaces = {
 'URL' : [{
     'wrapperCache': False,
 },
 {
     'workers': True,
     'wrapperCache': False,
 }],
 
-'VRFieldOfView': {
-    'wrapperCache': False,
-},
-
-'VRFieldOfViewReadOnly': {
-    'concrete': False,
-    'wrapperCache': False,
-},
-
 'VRDevice': {
     'concrete': False
 },
 
 'VTTCue': {
     'nativeType': 'mozilla::dom::TextTrackCue'
 },
 
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -689,16 +689,20 @@ void HTMLMediaElement::AbortExistingLoad
   mAutoplaying = true;
   mIsLoadingFromSourceChildren = false;
   mSuspendedAfterFirstFrame = false;
   mAllowSuspendAfterFirstFrame = true;
   mHaveQueuedSelectResource = false;
   mSuspendedForPreloadNone = false;
   mDownloadSuspendedByCache = false;
   mMediaInfo = MediaInfo();
+  mIsEncrypted = false;
+#ifdef MOZ_EME
+  mPendingEncryptedInitData.mInitDatas.Clear();
+#endif // MOZ_EME
   mSourcePointer = nullptr;
   mLastNextFrameStatus = NEXT_FRAME_UNINITIALIZED;
 
   mTags = nullptr;
 
   if (mNetworkState != nsIDOMHTMLMediaElement::NETWORK_EMPTY) {
     NS_ASSERTION(!mDecoder && !mSrcStream, "How did someone setup a new stream/decoder already?");
     // ChangeNetworkState() will call UpdateAudioChannelPlayingState()
@@ -3083,17 +3087,21 @@ void HTMLMediaElement::ProcessMediaFragm
     mFragmentStart = parser.GetStartTime();
   }
 }
 
 void HTMLMediaElement::MetadataLoaded(const MediaInfo* aInfo,
                                       nsAutoPtr<const MetadataTags> aTags)
 {
   mMediaInfo = *aInfo;
-  mIsEncrypted = aInfo->IsEncrypted();
+  mIsEncrypted = aInfo->IsEncrypted()
+#ifdef MOZ_EME
+                 || mPendingEncryptedInitData.IsEncrypted()
+#endif // MOZ_EME
+                 ;
   mTags = aTags.forget();
   mLoadedDataFired = false;
   ChangeReadyState(nsIDOMHTMLMediaElement::HAVE_METADATA);
 
   if (mIsEncrypted) {
     nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
     obs->NotifyObservers(static_cast<nsIContent*>(this), "media-eme-metadataloaded", nullptr);
   }
@@ -3110,18 +3118,22 @@ void HTMLMediaElement::MetadataLoaded(co
   }
   if (mIsEncrypted) {
     if (!mMediaSource && Preferences::GetBool("media.eme.mse-only", true)) {
       DecodeError();
       return;
     }
 
 #ifdef MOZ_EME
-    DispatchEncrypted(aInfo->mCrypto.mInitData, aInfo->mCrypto.mType);
-#endif
+    // Dispatch a distinct 'encrypted' event for each initData we have.
+    for (const auto& initData : mPendingEncryptedInitData.mInitDatas) {
+      DispatchEncrypted(initData.mInitData, initData.mType);
+    }
+    mPendingEncryptedInitData.mInitDatas.Clear();
+#endif // MOZ_EME
   }
 
   // Expose the tracks to JS directly.
   for (OutputMediaStream& out : mOutputStreams) {
     if (aInfo->HasAudio()) {
       TrackID audioTrackId = aInfo->mAudio.mTrackInfo.mOutputId;
       out.mStream->CreateDOMTrack(audioTrackId, MediaSegment::AUDIO);
     }
@@ -4474,16 +4486,23 @@ HTMLMediaElement::SetOnencrypted(EventHa
     elm->SetEventHandler(nsGkAtoms::onencrypted, EmptyString(), handler);
   }
 }
 
 void
 HTMLMediaElement::DispatchEncrypted(const nsTArray<uint8_t>& aInitData,
                                     const nsAString& aInitDataType)
 {
+  if (mReadyState == nsIDOMHTMLMediaElement::HAVE_NOTHING) {
+    // Ready state not HAVE_METADATA (yet), don't dispatch encrypted now.
+    // Queueing for later dispatch in MetadataLoaded.
+    mPendingEncryptedInitData.AddInitData(aInitDataType, aInitData);
+    return;
+  }
+
   nsRefPtr<MediaEncryptedEvent> event;
   if (IsCORSSameOrigin()) {
     event = MediaEncryptedEvent::Constructor(this, aInitDataType, aInitData);
   } else {
     event = MediaEncryptedEvent::Constructor(this);
   }
 
   nsRefPtr<AsyncEventDispatcher> asyncDispatcher =
--- a/dom/html/HTMLMediaElement.h
+++ b/dom/html/HTMLMediaElement.h
@@ -556,17 +556,16 @@ public:
                                          ErrorResult& aRv);
 
   mozilla::dom::EventHandlerNonNull* GetOnencrypted();
   void SetOnencrypted(mozilla::dom::EventHandlerNonNull* listener);
 
   void DispatchEncrypted(const nsTArray<uint8_t>& aInitData,
                          const nsAString& aInitDataType) override;
 
-
   bool IsEventAttributeName(nsIAtom* aName) override;
 
   // Returns the principal of the "top level" document; the origin displayed
   // in the URL bar of the browser window.
   already_AddRefed<nsIPrincipal> GetTopLevelPrincipal();
 
   bool ContainsRestrictedContent();
 #endif // MOZ_EME
@@ -1317,16 +1316,21 @@ protected:
   CORSMode mCORSMode;
 
   // Info about the played media.
   MediaInfo mMediaInfo;
 
   // True if the media has encryption information.
   bool mIsEncrypted;
 
+#ifdef MOZ_EME
+  // Init Data that needs to be sent in 'encrypted' events in MetadataLoaded().
+  EncryptionInfo mPendingEncryptedInitData;
+#endif // MOZ_EME
+
   // True if the media's channel's download has been suspended.
   bool mDownloadSuspendedByCache;
 
   // Audio Channel.
   AudioChannel mAudioChannel;
 
   // The audio channel has been faded.
   bool mAudioChannelFaded;
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -2021,18 +2021,18 @@ TabChild::RecvUpdateDimensions(const nsI
                       && (size.width != 0 && size.height != 0);
     if (initialSizing) {
       mHasValidInnerSize = true;
     }
 
     mOrientation = orientation;
     ScreenIntSize oldScreenSize = mInnerSize;
     mInnerSize = size;
-    mWidget->Resize(0, 0, size.width, size.height,
-                    true);
+    mWidget->Resize(rect.x + chromeDisp.x, rect.y + chromeDisp.y, size.width, size.height,
+                     true);
 
     nsCOMPtr<nsIBaseWindow> baseWin = do_QueryInterface(WebNavigation());
     baseWin->SetPositionAndSize(0, 0, size.width, size.height,
                                 true);
 
     if (initialSizing && mContentDocumentIsDisplayed) {
       // If this is the first time we're getting a valid mInnerSize, and the
       // before-first-paint event has already been handled, then we need to set
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -75,16 +75,17 @@
 #include "LoadContext.h"
 #include "nsNetCID.h"
 #include "nsIAuthInformation.h"
 #include "nsIAuthPromptCallback.h"
 #include "nsAuthInformationHolder.h"
 #include "nsICancelable.h"
 #include "gfxPrefs.h"
 #include "nsILoginManagerPrompter.h"
+#include "nsPIWindowRoot.h"
 #include <algorithm>
 
 using namespace mozilla::dom;
 using namespace mozilla::ipc;
 using namespace mozilla::layers;
 using namespace mozilla::layout;
 using namespace mozilla::services;
 using namespace mozilla::widget;
@@ -262,16 +263,17 @@ TabParent::TabParent(nsIContentParent* a
   , mIMECompositionRectOffset(0)
   , mRect(0, 0, 0, 0)
   , mDimensions(0, 0)
   , mOrientation(0)
   , mDPI(0)
   , mDefaultScale(0)
   , mShown(false)
   , mUpdatedDimensions(false)
+  , mChromeOffset(0, 0)
   , mManager(aManager)
   , mMarkedDestroying(false)
   , mIsDestroyed(false)
   , mAppPackageFileDescriptorSent(false)
   , mSendOfflineStatus(true)
   , mChromeFlags(aChromeFlags)
   , mInitedByParent(false)
   , mTabId(aTabId)
@@ -320,21 +322,47 @@ void
 TabParent::CacheFrameLoader(nsFrameLoader* aFrameLoader)
 {
   mFrameLoader = aFrameLoader;
 }
 
 void
 TabParent::SetOwnerElement(Element* aElement)
 {
+  // If we held previous content then unregister for its events.
+  RemoveWindowListeners();
+
+  // Update to the new content, and register to listen for events from it.
   mFrameElement = aElement;
+  if (mFrameElement && mFrameElement->OwnerDoc()->GetWindow()) {
+    nsCOMPtr<nsPIDOMWindow> window = mFrameElement->OwnerDoc()->GetWindow();
+    nsCOMPtr<EventTarget> eventTarget = window->GetTopWindowRoot();
+    if (eventTarget) {
+      eventTarget->AddEventListener(NS_LITERAL_STRING("MozUpdateWindowPos"),
+                                    this, false, false);
+    }
+  }
+
   TryCacheDPIAndScale();
 }
 
 void
+TabParent::RemoveWindowListeners()
+{
+  if (mFrameElement && mFrameElement->OwnerDoc()->GetWindow()) {
+    nsCOMPtr<nsPIDOMWindow> window = mFrameElement->OwnerDoc()->GetWindow();
+    nsCOMPtr<EventTarget> eventTarget = window->GetTopWindowRoot();
+    if (eventTarget) {
+      eventTarget->RemoveEventListener(NS_LITERAL_STRING("MozUpdateWindowPos"),
+                                       this, false);
+    }
+  }
+}
+
+void
 TabParent::GetAppType(nsAString& aOut)
 {
   aOut.Truncate();
   nsCOMPtr<Element> elem = do_QueryInterface(mFrameElement);
   if (!elem) {
     return;
   }
 
@@ -875,34 +903,43 @@ TabParent::RecvSetDimensions(const uint3
     return true;
   }
 
   MOZ_ASSERT(false, "Unknown flags!");
   return false;
 }
 
 void
-TabParent::UpdateDimensions(const nsIntRect& rect, const ScreenIntSize& size,
-                            const nsIntPoint& aChromeDisp)
+TabParent::UpdateDimensions(const nsIntRect& rect, const ScreenIntSize& size)
 {
   if (mIsDestroyed) {
     return;
   }
   hal::ScreenConfiguration config;
   hal::GetCurrentScreenConfiguration(&config);
   ScreenOrientation orientation = config.orientation();
+  nsIntPoint chromeOffset = -LayoutDevicePixel::ToUntyped(GetChildProcessOffset());
 
   if (!mUpdatedDimensions || mOrientation != orientation ||
-      mDimensions != size || !mRect.IsEqualEdges(rect)) {
+      mDimensions != size || !mRect.IsEqualEdges(rect) ||
+      chromeOffset != mChromeOffset) {
+    nsCOMPtr<nsIWidget> widget = GetWidget();
+    nsIntRect contentRect = rect;
+    if (widget) {
+      contentRect.x += widget->GetClientOffset().x;
+      contentRect.y += widget->GetClientOffset().y;
+    }
+
     mUpdatedDimensions = true;
-    mRect = rect;
+    mRect = contentRect;
     mDimensions = size;
     mOrientation = orientation;
-
-    unused << SendUpdateDimensions(mRect, mDimensions, mOrientation, aChromeDisp);
+    mChromeOffset = chromeOffset;
+
+    unused << SendUpdateDimensions(mRect, mDimensions, mOrientation, mChromeOffset);
   }
 }
 
 void
 TabParent::UpdateFrame(const FrameMetrics& aFrameMetrics)
 {
   if (!mIsDestroyed) {
     unused << SendUpdateFrame(aFrameMetrics);
@@ -2735,16 +2772,37 @@ TabParent::AllocPPluginWidgetParent()
 
 bool
 TabParent::DeallocPPluginWidgetParent(mozilla::plugins::PPluginWidgetParent* aActor)
 {
   delete aActor;
   return true;
 }
 
+nsresult
+TabParent::HandleEvent(nsIDOMEvent* aEvent)
+{
+  nsAutoString eventType;
+  aEvent->GetType(eventType);
+
+  if (eventType.EqualsLiteral("MozUpdateWindowPos") && !mIsDestroyed) {
+    // This event is sent when the widget moved.  Therefore we only update
+    // the position.
+    nsRefPtr<nsFrameLoader> frameLoader = GetFrameLoader();
+    if (!frameLoader) {
+      return NS_OK;
+    }
+    nsIntRect windowDims;
+    NS_ENSURE_SUCCESS(frameLoader->GetWindowDimensions(windowDims), NS_ERROR_FAILURE);
+    UpdateDimensions(windowDims, mDimensions);
+    return NS_OK;
+  }
+  return NS_OK;
+}
+
 class FakeChannel final : public nsIChannel,
                           public nsIAuthPromptCallback,
                           public nsIInterfaceRequestor,
                           public nsILoadContext
 {
 public:
   FakeChannel(const nsCString& aUri, uint64_t aCallbackId, Element* aElement)
     : mCallbackId(aCallbackId)
--- a/dom/ipc/TabParent.h
+++ b/dom/ipc/TabParent.h
@@ -55,29 +55,32 @@ struct IMENotification;
 namespace dom {
 
 class ClonedMessageData;
 class nsIContentParent;
 class Element;
 struct StructuredCloneData;
 
 class TabParent final : public PBrowserParent
+                      , public nsIDOMEventListener
                       , public nsITabParent
                       , public nsIAuthPromptProvider
                       , public nsISecureBrowserUI
                       , public nsSupportsWeakReference
                       , public TabContext
 {
     typedef mozilla::dom::ClonedMessageData ClonedMessageData;
 
     virtual ~TabParent();
 
 public:
     // nsITabParent
     NS_DECL_NSITABPARENT
+    // nsIDOMEventListener interfaces
+    NS_DECL_NSIDOMEVENTLISTENER
 
     TabParent(nsIContentParent* aManager,
               const TabId& aTabId,
               const TabContext& aContext,
               uint32_t aChromeFlags);
     Element* GetOwnerElement() const { return mFrameElement; }
     void SetOwnerElement(Element* aElement);
 
@@ -102,16 +105,18 @@ public:
     }
 
     already_AddRefed<nsILoadContext> GetLoadContext();
 
     nsIXULBrowserWindow* GetXULBrowserWindow();
 
     void Destroy();
 
+    void RemoveWindowListeners();
+
     virtual bool RecvMoveFocus(const bool& aForward) override;
     virtual bool RecvEvent(const RemoteDOMEvent& aEvent) override;
     virtual bool RecvReplyKeyEvent(const WidgetKeyboardEvent& aEvent) override;
     virtual bool RecvDispatchAfterKeyboardEvent(const WidgetKeyboardEvent& aEvent) override;
     virtual bool RecvBrowserFrameOpenWindow(PBrowserParent* aOpener,
                                             const nsString& aURL,
                                             const nsString& aName,
                                             const nsString& aFeatures,
@@ -220,18 +225,17 @@ public:
     AllocPColorPickerParent(const nsString& aTitle, const nsString& aInitialColor) override;
     virtual bool DeallocPColorPickerParent(PColorPickerParent* aColorPicker) override;
 
     void LoadURL(nsIURI* aURI);
     // XXX/cjones: it's not clear what we gain by hiding these
     // message-sending functions under a layer of indirection and
     // eating the return values
     void Show(const ScreenIntSize& size, bool aParentIsActive);
-    void UpdateDimensions(const nsIntRect& rect, const ScreenIntSize& size,
-                          const nsIntPoint& chromeDisp);
+    void UpdateDimensions(const nsIntRect& rect, const ScreenIntSize& size);
     void UpdateFrame(const layers::FrameMetrics& aFrameMetrics);
     void UIResolutionChanged();
     void RequestFlingSnap(const FrameMetrics::ViewID& aScrollId,
                           const mozilla::CSSPoint& aDestination);
     void AcknowledgeScrollUpdate(const ViewID& aScrollId, const uint32_t& aScrollGeneration);
     void HandleDoubleTap(const CSSPoint& aPoint,
                          Modifiers aModifiers,
                          const ScrollableLayerGuid& aGuid);
@@ -422,16 +426,17 @@ protected:
 
     nsIntRect mRect;
     ScreenIntSize mDimensions;
     ScreenOrientation mOrientation;
     float mDPI;
     CSSToLayoutDeviceScale mDefaultScale;
     bool mShown;
     bool mUpdatedDimensions;
+    nsIntPoint mChromeOffset;
 
 private:
     already_AddRefed<nsFrameLoader> GetFrameLoader(bool aUseCachedFrameLoaderAfterDestroy = false) const;
     layout::RenderFrameParent* GetRenderFrame();
     nsRefPtr<nsIContentParent> mManager;
     void TryCacheDPIAndScale();
 
     CSSPoint AdjustTapToChildWidget(const CSSPoint& aPoint);
--- a/dom/media/MediaDecoderOwner.h
+++ b/dom/media/MediaDecoderOwner.h
@@ -131,19 +131,19 @@ public:
   virtual VideoFrameContainer* GetVideoFrameContainer() = 0;
 
   // Called by the media decoder object, on the main thread,
   // when the connection between Rtsp server and client gets lost.
   virtual void ResetConnectionState() = 0;
 
 #ifdef MOZ_EME
   // Dispatches a "encrypted" event to the HTMLMediaElement, with the
-  // provided init data.
+  // provided init data. Actual dispatch may be delayed until HAVE_METADATA.
   // Main thread only.
   virtual void DispatchEncrypted(const nsTArray<uint8_t>& aInitData,
                                  const nsAString& aInitDataType) = 0;
-#endif
+#endif // MOZ_EME
 };
 
 }
 
 #endif
 
--- a/dom/media/MediaInfo.h
+++ b/dom/media/MediaInfo.h
@@ -100,43 +100,68 @@ public:
   // True if we have an active audio bitstream.
   bool mHasAudio;
 
   TrackInfo mTrackInfo;
 };
 
 class EncryptionInfo {
 public:
-  EncryptionInfo() : mIsEncrypted(false) {}
+  struct InitData {
+    template<typename AInitDatas>
+    InitData(const nsAString& aType, AInitDatas&& aInitData)
+      : mType(aType)
+      , mInitData(Forward<AInitDatas>(aInitData))
+    {
+    }
 
-  // Encryption type to be passed to JS. Usually `cenc'.
-  nsString mType;
+    // Encryption type to be passed to JS. Usually `cenc'.
+    nsString mType;
 
-  // Encryption data.
-  nsTArray<uint8_t> mInitData;
+    // Encryption data.
+    nsTArray<uint8_t> mInitData;
+  };
+  typedef nsTArray<InitData> InitDatas;
 
   // True if the stream has encryption metadata
-  bool mIsEncrypted;
+  bool IsEncrypted() const
+  {
+    return !mInitDatas.IsEmpty();
+  }
+
+  template<typename AInitDatas>
+  void AddInitData(const nsAString& aType, AInitDatas&& aInitData)
+  {
+    mInitDatas.AppendElement(InitData(aType, Forward<AInitDatas>(aInitData)));
+  }
+
+  void AddInitData(const EncryptionInfo& aInfo)
+  {
+    mInitDatas.AppendElements(aInfo.mInitDatas);
+  }
+
+  // One 'InitData' per encrypted buffer.
+  InitDatas mInitDatas;
 };
 
 class MediaInfo {
 public:
   bool HasVideo() const
   {
     return mVideo.mHasVideo;
   }
 
   bool HasAudio() const
   {
     return mAudio.mHasAudio;
   }
 
   bool IsEncrypted() const
   {
-    return mCrypto.mIsEncrypted;
+    return mCrypto.IsEncrypted();
   }
 
   bool HasValidMedia() const
   {
     return HasVideo() || HasAudio();
   }
 
   // TODO: Store VideoInfo and AudioIndo in arrays to support multi-tracks.
--- a/dom/media/fmp4/MP4Reader.cpp
+++ b/dom/media/fmp4/MP4Reader.cpp
@@ -259,16 +259,44 @@ MP4Reader::Init(MediaDecoderReader* aClo
     sSetupPrefCache = true;
     Preferences::AddBoolVarCache(&sIsEMEEnabled, "media.eme.enabled", false);
     Preferences::AddBoolVarCache(&sDemuxSkipToNextKeyframe, "media.fmp4.demux-skip", true);
   }
 
   return NS_OK;
 }
 
+#ifdef MOZ_EME
+class DispatchKeyNeededEvent : public nsRunnable {
+public:
+  DispatchKeyNeededEvent(AbstractMediaDecoder* aDecoder,
+                         nsTArray<uint8_t>& aInitData,
+                         const nsString& aInitDataType)
+    : mDecoder(aDecoder)
+    , mInitData(aInitData)
+    , mInitDataType(aInitDataType)
+  {
+  }
+  NS_IMETHOD Run() {
+    // Note: Null check the owner, as the decoder could have been shutdown
+    // since this event was dispatched.
+    MediaDecoderOwner* owner = mDecoder->GetOwner();
+    if (owner) {
+      owner->DispatchEncrypted(mInitData, mInitDataType);
+    }
+    mDecoder = nullptr;
+    return NS_OK;
+  }
+private:
+  nsRefPtr<AbstractMediaDecoder> mDecoder;
+  nsTArray<uint8_t> mInitData;
+  nsString mInitDataType;
+};
+#endif // MOZ_EME
+
 void MP4Reader::RequestCodecResource() {
   if (mVideo.mDecoder) {
     mVideo.mDecoder->AllocateMediaResources();
   }
 }
 
 bool MP4Reader::IsWaitingMediaResources() {
   return mVideo.mDecoder && mVideo.mDecoder->IsWaitingMediaResources();
@@ -363,17 +391,17 @@ MP4Reader::ReadMetadata(MediaInfo* aInfo
     if (mAudio.mActive) {
       mAudio.mTrackDemuxer = new MP4AudioDemuxer(mDemuxer);
     }
     mCrypto = mDemuxer->Crypto();
 
     {
       MonitorAutoUnlock unlock(mDemuxerMonitor);
       ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
-      mInfo.mCrypto.mIsEncrypted = mIsEncrypted = mCrypto.valid;
+      mIsEncrypted = mCrypto.valid;
     }
 
     // Remember that we've initialized the demuxer, so that if we're decoding
     // an encrypted stream and we need to wait for a CDM to be set, we don't
     // need to reinit the demuxer.
     mDemuxerInitialized = true;
   } else if (mPlatform && !IsWaitingMediaResources()) {
     *aInfo = mInfo;
@@ -395,25 +423,31 @@ MP4Reader::ReadMetadata(MediaInfo* aInfo
     mVideo.mCallback = new DecoderCallback(this, kVideo);
 
     // Collect telemetry from h264 AVCC SPS.
     if (!mFoundSPSForTelemetry) {
       mFoundSPSForTelemetry = AccumulateSPSTelemetry(video.extra_data);
     }
   }
 
-  if (mIsEncrypted) {
+  if (mCrypto.valid) {
     nsTArray<uint8_t> initData;
     ExtractCryptoInitData(initData);
     if (initData.Length() == 0) {
       return NS_ERROR_FAILURE;
     }
 
-    mInfo.mCrypto.mInitData = initData;
-    mInfo.mCrypto.mType = NS_LITERAL_STRING("cenc");
+#ifdef MOZ_EME
+    // Try and dispatch 'encrypted'. Won't go if ready state still HAVE_NOTHING.
+    NS_DispatchToMainThread(
+      new DispatchKeyNeededEvent(mDecoder, initData, NS_LITERAL_STRING("cenc")));
+#endif // MOZ_EME
+    // Add init data to info, will get sent from HTMLMediaElement::MetadataLoaded
+    // (i.e., when transitioning from HAVE_NOTHING to HAVE_METADATA).
+    mInfo.mCrypto.AddInitData(NS_LITERAL_STRING("cenc"), Move(initData));
   }
 
   // Get the duration, and report it to the decoder if we have it.
   Microseconds duration;
   {
     MonitorAutoLock lock(mDemuxerMonitor);
     duration = mDemuxer->Duration();
   }
--- a/dom/media/fmp4/MP4Reader.h
+++ b/dom/media/fmp4/MP4Reader.h
@@ -270,18 +270,16 @@ private:
   // frames every time that DecodeVideoData() is called, and report the
   // delta there.
   uint64_t mLastReportedNumDecodedFrames;
 
   DecoderData& GetDecoderData(mp4_demuxer::TrackType aTrack);
 
   layers::LayersBackend mLayersBackendType;
 
-  nsTArray<nsTArray<uint8_t>> mInitDataEncountered;
-
   // True if we've read the streams' metadata.
   bool mDemuxerInitialized;
 
   // True if we've gathered telemetry from an SPS.
   bool mFoundSPSForTelemetry;
 
   // Synchronized by decoder monitor.
   bool mIsEncrypted;
--- a/dom/media/mediasource/MediaSourceReader.cpp
+++ b/dom/media/mediasource/MediaSourceReader.cpp
@@ -1063,32 +1063,16 @@ MediaSourceReader::MaybeNotifyHaveData()
     if (ended || haveVideo) {
       WaitPromise(MediaData::VIDEO_DATA).ResolveIfExists(MediaData::VIDEO_DATA, __func__);
     }
   }
   MSE_DEBUG("isSeeking=%d haveAudio=%d, haveVideo=%d ended=%d",
             IsSeeking(), haveAudio, haveVideo, ended);
 }
 
-static void
-CombineEncryptionData(EncryptionInfo& aTo, const EncryptionInfo& aFrom)
-{
-  if (!aFrom.mIsEncrypted) {
-    return;
-  }
-  aTo.mIsEncrypted = true;
-
-  if (!aTo.mType.IsEmpty() && !aTo.mType.Equals(aFrom.mType)) {
-    NS_WARNING("mismatched encryption types");
-  }
-
-  aTo.mType = aFrom.mType;
-  aTo.mInitData.AppendElements(aFrom.mInitData);
-}
-
 nsresult
 MediaSourceReader::ReadMetadata(MediaInfo* aInfo, MetadataTags** aTags)
 {
   ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
 
   MSE_DEBUG("tracks=%u/%u audio=%p video=%p",
             mEssentialTrackBuffers.Length(), mTrackBuffers.Length(),
             mAudioTrack.get(), mVideoTrack.get());
@@ -1102,30 +1086,30 @@ MediaSourceReader::ReadMetadata(MediaInf
 
   if (mAudioTrack) {
     MOZ_ASSERT(mAudioTrack->IsReady());
     mAudioSourceDecoder = mAudioTrack->Decoders()[0];
 
     const MediaInfo& info = GetAudioReader()->GetMediaInfo();
     MOZ_ASSERT(info.HasAudio());
     mInfo.mAudio = info.mAudio;
-    CombineEncryptionData(mInfo.mCrypto, info.mCrypto);
+    mInfo.mCrypto.AddInitData(info.mCrypto);
     MSE_DEBUG("audio reader=%p duration=%lld",
               mAudioSourceDecoder.get(),
               mAudioSourceDecoder->GetReader()->GetDecoder()->GetMediaDuration());
   }
 
   if (mVideoTrack) {
     MOZ_ASSERT(mVideoTrack->IsReady());
     mVideoSourceDecoder = mVideoTrack->Decoders()[0];
 
     const MediaInfo& info = GetVideoReader()->GetMediaInfo();
     MOZ_ASSERT(info.HasVideo());
     mInfo.mVideo = info.mVideo;
-    CombineEncryptionData(mInfo.mCrypto, info.mCrypto);
+    mInfo.mCrypto.AddInitData(info.mCrypto);
     MSE_DEBUG("video reader=%p duration=%lld",
               GetVideoReader(),
               GetVideoReader()->GetDecoder()->GetMediaDuration());
   }
 
   *aInfo = mInfo;
   *aTags = nullptr; // TODO: Handle metadata.
 
--- a/dom/media/test/manifest.js
+++ b/dom/media/test/manifest.js
@@ -659,16 +659,17 @@ var gEMETests = [
       }
     ],
     keys: {
       // "keyid" : "key"
       "7e571d037e571d037e571d037e571d03" : "7e5733337e5733337e5733337e573333",
       "7e571d047e571d047e571d047e571d04" : "7e5744447e5744447e5744447e574444",
     },
     sessionType:"temporary",
+    sessionCount:1,
     duration:1.60,
   },
   {
     name:"bipbop-cenc-videoinit.mp4",
     tracks: [
       {
         name:"video",
         type:"video/mp4; codecs=\"avc1.64000d\"",
@@ -679,16 +680,17 @@ var gEMETests = [
       }
     ],
     keys: {
       // "keyid" : "key"
       "7e571d037e571d037e571d037e571d03" : "7e5733337e5733337e5733337e573333",
       "7e571d047e571d047e571d047e571d04" : "7e5744447e5744447e5744447e574444",
     },
     sessionType:"temporary",
+    sessionCount:1,
     crossOrigin:true,
     duration:1.60,
   },
   {
     name:"bipbop-cenc-videoinit.mp4",
     tracks: [
       {
         name:"audio",
@@ -709,16 +711,17 @@ var gEMETests = [
       },
     ],
     keys: {
       // "keyid" : "key"
       "7e571d037e571d037e571d037e571d03" : "7e5733337e5733337e5733337e573333",
       "7e571d047e571d047e571d047e571d04" : "7e5744447e5744447e5744447e574444",
     },
     sessionType:"temporary",
+    sessionCount:2,
     duration:1.60,
   },
   {
     name:"bipbop-cenc-videoinit.mp4",
     tracks: [
       {
         name:"audio",
         type:"audio/mp4; codecs=\"mp4a.40.2\"",
@@ -738,16 +741,17 @@ var gEMETests = [
       },
     ],
     keys: {
       // "keyid" : "key"
       "7e571d037e571d037e571d037e571d03" : "7e5733337e5733337e5733337e573333",
       "7e571d047e571d047e571d047e571d04" : "7e5744447e5744447e5744447e574444",
     },
     sessionType:"temporary",
+    sessionCount:2,
     crossOrigin:true,
     duration:1.60,
   },
 ];
 
 var gEMENonMSEFailTests = [
   {
     name:"short-cenc.mp4",
--- a/dom/media/test/test_eme_playback.html
+++ b/dom/media/test/test_eme_playback.html
@@ -43,35 +43,37 @@ function startTest(test, token)
     {
       onsessioncreated: function(session) {
         sessions.push(session);
         session.addEventListener("keystatuseschange", KeysChangeFunc(session, test.keys, token), false);
       }
     }
   );
 
-  var gotEncrypted = false;
+  var gotEncrypted = 0;
   var gotPlaying = false;
 
   v.addEventListener("encrypted", function(ev) {
-    gotEncrypted = true;
+    gotEncrypted += 1;
   });
 
   v.addEventListener("playing", function () { gotPlaying = true; });
 
   v.addEventListener("loadedmetadata", function() {
     ok(SpecialPowers.do_lookupGetter(v, "isEncrypted").apply(v),
        TimeStamp(token) + " isEncrypted should be true");
     is(v.isEncrypted, undefined, "isEncrypted should not be accessible from content");
   });
 
   v.addEventListener("ended", function(ev) {
     ok(true, TimeStamp(token) + " got ended event");
 
-    ok(gotEncrypted, TimeStamp(token) + " encrypted event should have fired");
+    is(gotEncrypted, test.sessionCount,
+       TimeStamp(token) + " encrypted events expected: " + test.sessionCount
+       + ", actual: " + gotEncrypted);
     ok(gotPlaying, TimeStamp(token) + " playing event should have fired");
 
     ok(Math.abs(test.duration - v.duration) < 0.1,
        TimeStamp(token) + " Duration of video should be corrrect");
     ok(Math.abs(test.duration - v.currentTime) < 0.1,
        TimeStamp(token) + " Current time should be same as duration");
 
     // Verify all sessions had all keys went sent the to the CDM usable, and thus
--- a/dom/media/webaudio/test/test_mediaElementAudioSourceNodeCrossOrigin.html
+++ b/dom/media/webaudio/test/test_mediaElementAudioSourceNodeCrossOrigin.html
@@ -6,16 +6,19 @@
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 </head>
 <body>
 <pre id="test">
 <script class="testbody" type="text/javascript">
 SimpleTest.waitForExplicitFinish();
 
+// Turn off the authentication dialog blocking for this test.
+SpecialPowers.setIntPref("network.auth.allow-subresource-auth", 2)
+
 var tests = [
   // Not the same origin no CORS asked for, should have silence
   { url: "http://example.org:80/tests/dom/media/webaudio/test/small-shot.ogg",
     cors: null,
     expectSilence: true },
   // Same origin, should have sound
   { url: "small-shot.ogg",
     cors: null,
--- a/dom/plugins/base/nsPluginInstanceOwner.cpp
+++ b/dom/plugins/base/nsPluginInstanceOwner.cpp
@@ -785,28 +785,27 @@ NPBool nsPluginInstanceOwner::ConvertPoi
   nsPoint windowPosition = AsNsPoint(rootWidget->GetWindowPosition()) / scaleFactor;
 
   // Window size is tab size + chrome size.
   nsIntRect tabContentBounds;
   NS_ENSURE_SUCCESS(puppetWidget->GetBounds(tabContentBounds), false);
   tabContentBounds.ScaleInverseRoundOut(scaleFactor);
   int32_t windowH = tabContentBounds.height + int(chromeSize.y);
 
-  // This is actually relative to window-chrome.
   nsPoint pluginPosition = AsNsPoint(pluginFrame->GetScreenRect().TopLeft());
 
   // Convert (sourceX, sourceY) to 'real' (not PuppetWidget) screen space.
   // In OSX, the Y-axis increases upward, which is the reverse of ours.
   // We want OSX coordinates for window and screen so those equations are swapped.
   nsPoint sourcePoint(sourceX, sourceY);
   nsPoint screenPoint;
   switch (sourceSpace) {
     case NPCoordinateSpacePlugin:
-      screenPoint = sourcePoint + pluginFrame->GetContentRectRelativeToSelf().TopLeft() +
-        chromeSize + pluginPosition + windowPosition;
+      screenPoint = sourcePoint + pluginPosition +
+        pluginFrame->GetContentRectRelativeToSelf().TopLeft() / nsPresContext::AppUnitsPerCSSPixel();
       break;
     case NPCoordinateSpaceWindow:
       screenPoint = nsPoint(sourcePoint.x, windowH-sourcePoint.y) +
         windowPosition;
       break;
     case NPCoordinateSpaceFlippedWindow:
       screenPoint = sourcePoint + windowPosition;
       break;
@@ -819,18 +818,18 @@ NPBool nsPluginInstanceOwner::ConvertPoi
     default:
       return false;
   }
 
   // Convert from screen to dest space.
   nsPoint destPoint;
   switch (destSpace) {
     case NPCoordinateSpacePlugin:
-      destPoint = screenPoint - pluginFrame->GetContentRectRelativeToSelf().TopLeft() -
-        chromeSize - pluginPosition - windowPosition;
+      destPoint = screenPoint - pluginPosition -
+        pluginFrame->GetContentRectRelativeToSelf().TopLeft() / nsPresContext::AppUnitsPerCSSPixel();
       break;
     case NPCoordinateSpaceWindow:
       destPoint = screenPoint - windowPosition;
       destPoint.y = windowH - destPoint.y;
       break;
     case NPCoordinateSpaceFlippedWindow:
       destPoint = screenPoint - windowPosition;
       break;
--- a/dom/vr/VRDevice.cpp
+++ b/dom/vr/VRDevice.cpp
@@ -12,40 +12,119 @@
 #include "gfxVR.h"
 #include "nsIFrame.h"
 
 using namespace mozilla::gfx;
 
 namespace mozilla {
 namespace dom {
 
-VRFieldOfView*
+NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(VRFieldOfViewReadOnly, mParent)
+NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(VRFieldOfViewReadOnly, AddRef)
+NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(VRFieldOfViewReadOnly, Release)
+
+JSObject*
+VRFieldOfViewReadOnly::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
+{
+  return VRFieldOfViewReadOnlyBinding::Wrap(aCx, this, aGivenProto);
+}
+
+already_AddRefed<VRFieldOfView>
 VRFieldOfView::Constructor(const GlobalObject& aGlobal, const VRFieldOfViewInit& aParams,
                            ErrorResult& aRV)
 {
-  return new VRFieldOfView(aParams.mUpDegrees, aParams.mRightDegrees,
-                           aParams.mDownDegrees, aParams.mLeftDegrees);
+  nsRefPtr<VRFieldOfView> fov =
+    new VRFieldOfView(aGlobal.GetAsSupports(),
+                      aParams.mUpDegrees, aParams.mRightDegrees,
+                      aParams.mDownDegrees, aParams.mLeftDegrees);
+  return fov.forget();
 }
 
-VRFieldOfView*
+already_AddRefed<VRFieldOfView>
 VRFieldOfView::Constructor(const GlobalObject& aGlobal,
                            double aUpDegrees, double aRightDegrees,
                            double aDownDegrees, double aLeftDegrees,
                            ErrorResult& aRV)
 {
-  return new VRFieldOfView(aUpDegrees, aRightDegrees, aDownDegrees,
-                           aLeftDegrees);
+  nsRefPtr<VRFieldOfView> fov =
+    new VRFieldOfView(aGlobal.GetAsSupports(),
+                      aUpDegrees, aRightDegrees, aDownDegrees,
+                      aLeftDegrees);
+  return fov.forget();
+}
+
+JSObject*
+VRFieldOfView::WrapObject(JSContext* aCx,
+                          JS::Handle<JSObject*> aGivenProto)
+{
+  return VRFieldOfViewBinding::Wrap(aCx, this, aGivenProto);
+}
+
+NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(VREyeParameters, mParent, mMinFOV, mMaxFOV, mRecFOV, mCurFOV, mEyeTranslation, mRenderRect)
+NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(VREyeParameters, AddRef)
+NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(VREyeParameters, Release)
+
+VREyeParameters::VREyeParameters(nsISupports* aParent,
+                                 const gfx::VRFieldOfView& aMinFOV,
+                                 const gfx::VRFieldOfView& aMaxFOV,
+                                 const gfx::VRFieldOfView& aRecFOV,
+                                 const gfx::Point3D& aEyeTranslation,
+                                 const gfx::VRFieldOfView& aCurFOV,
+                                 const gfx::IntRect& aRenderRect)
+  : mParent(aParent)
+{
+  mMinFOV = new VRFieldOfView(aParent, aMinFOV);
+  mMaxFOV = new VRFieldOfView(aParent, aMaxFOV);
+  mRecFOV = new VRFieldOfView(aParent, aRecFOV);
+  mCurFOV = new VRFieldOfView(aParent, aCurFOV);
+
+  mEyeTranslation = new DOMPoint(aParent, aEyeTranslation.x, aEyeTranslation.y, aEyeTranslation.z, 0.0);
+  mRenderRect = new DOMRect(aParent, aRenderRect.x, aRenderRect.y, aRenderRect.width, aRenderRect.height);
 }
 
-bool
-VRFieldOfView::WrapObject(JSContext* aCx,
-                          JS::Handle<JSObject*> aGivenProto,
-                          JS::MutableHandle<JSObject*> aReflector)
+VRFieldOfView*
+VREyeParameters::MinimumFieldOfView()
+{
+  return mMinFOV;
+}
+
+VRFieldOfView*
+VREyeParameters::MaximumFieldOfView()
+{
+  return mMaxFOV;
+}
+
+VRFieldOfView*
+VREyeParameters::RecommendedFieldOfView()
 {
-  return VRFieldOfViewBinding::Wrap(aCx, this, aGivenProto, aReflector);
+  return mRecFOV;
+}
+
+VRFieldOfView*
+VREyeParameters::CurrentFieldOfView()
+{
+  return mCurFOV;
+}
+
+DOMPoint*
+VREyeParameters::EyeTranslation()
+{
+  return mEyeTranslation;
+}
+
+DOMRect*
+VREyeParameters::RenderRect()
+{
+  return mRenderRect;
+}
+
+JSObject*
+VREyeParameters::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
+{
+  return VREyeParametersBinding::Wrap(aCx, this, aGivenProto);
 }
 
 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(VRPositionState, mParent)
 NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(VRPositionState, AddRef)
 NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(VRPositionState, Release)
 
 VRPositionState::VRPositionState(nsISupports* aParent, const gfx::VRHMDSensorState& aState)
   : mParent(aParent)
@@ -121,57 +200,40 @@ HMDVRDevice::WrapObject(JSContext* aCx, 
 }
 
 /* virtual */ JSObject*
 PositionSensorVRDevice::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
 {
   return PositionSensorVRDeviceBinding::Wrap(aCx, this, aGivenProto);
 }
 
-static void
-ReleaseHMDInfoRef(void *, nsIAtom*, void *aPropertyValue, void *)
-{
-  if (aPropertyValue) {
-    static_cast<VRHMDInfo*>(aPropertyValue)->Release();
-  }
-}
-
-void
-HMDVRDevice::XxxToggleElementVR(Element& aElement)
-{
-  VRHMDInfo* hmdPtr = static_cast<VRHMDInfo*>(aElement.GetProperty(nsGkAtoms::vr_state));
-  if (hmdPtr) {
-    aElement.DeleteProperty(nsGkAtoms::vr_state);
-    return;
-  }
-
-  nsRefPtr<VRHMDInfo> hmdRef = mHMD;
-  aElement.SetProperty(nsGkAtoms::vr_state, hmdRef.forget().take(),
-                       ReleaseHMDInfoRef,
-                       true);
-}
-
 namespace {
 
-gfx::VRHMDInfo::Eye
-EyeToEye(const VREye& aEye)
-{
-  return aEye == VREye::Left ? gfx::VRHMDInfo::Eye_Left : gfx::VRHMDInfo::Eye_Right;
-}
-
 class HMDInfoVRDevice : public HMDVRDevice
 {
 public:
   HMDInfoVRDevice(nsISupports* aParent, gfx::VRHMDInfo* aHMD)
     : HMDVRDevice(aParent, aHMD)
   {
     // XXX TODO use real names/IDs
-    mHWID.AppendPrintf("HMDInfo-0x%llx", aHMD);
-    mDeviceId.AssignLiteral("somedevid");
-    mDeviceName.AssignLiteral("HMD Device");
+    uint64_t hmdid = reinterpret_cast<uint64_t>(aHMD);
+
+    mHWID.Truncate();
+    mHWID.AppendPrintf("HMDInfo-0x%llx", hmdid);
+
+    mDeviceId.Truncate();
+    mDeviceId.AppendPrintf("HMDInfo-dev-0x%llx", hmdid);
+
+    if (aHMD->GetType() == VRHMDType::Oculus) {
+      mDeviceName.AssignLiteral("VR HMD Device (oculus)");
+    } else if (aHMD->GetType() == VRHMDType::Cardboard) {
+      mDeviceName.AssignLiteral("VR HMD Device (cardboard)");
+    } else {
+      mDeviceName.AssignLiteral("VR HMD Device (unknown)");
+    }
 
     mValid = true;
   }
 
   virtual ~HMDInfoVRDevice() { }
 
   /* If a field of view that is set to all 0's is passed in,
    * the recommended field of view for that eye is used.
@@ -188,116 +250,112 @@ public:
     if (left.IsZero())
       left = mHMD->GetRecommendedEyeFOV(VRHMDInfo::Eye_Left);
     if (right.IsZero())
       right = mHMD->GetRecommendedEyeFOV(VRHMDInfo::Eye_Right);
 
     mHMD->SetFOV(left, right, zNear, zFar);
   }
 
-  virtual already_AddRefed<DOMPoint> GetEyeTranslation(VREye aEye) override
-  {
-    gfx::Point3D p = mHMD->GetEyeTranslation(EyeToEye(aEye));
-
-    nsRefPtr<DOMPoint> obj = new DOMPoint(mParent, p.x, p.y, p.z, 0.0);
-    return obj.forget();
-  }
-
-  virtual VRFieldOfView* GetCurrentEyeFieldOfView(VREye aEye) override
-  {
-    return CopyFieldOfView(mHMD->GetEyeFOV(EyeToEye(aEye)));
-  }
-
-  virtual VRFieldOfView* GetRecommendedEyeFieldOfView(VREye aEye) override
+  virtual already_AddRefed<VREyeParameters> GetEyeParameters(VREye aEye) override
   {
-    return CopyFieldOfView(mHMD->GetRecommendedEyeFOV(EyeToEye(aEye)));
-  }
-
-  virtual VRFieldOfView* GetMaximumEyeFieldOfView(VREye aEye) override
-  {
-    return CopyFieldOfView(mHMD->GetMaximumEyeFOV(EyeToEye(aEye)));
-  }
-
-  virtual already_AddRefed<DOMRect> GetRecommendedEyeRenderRect(VREye aEye) override
-  {
-    const IntSize& a(mHMD->SuggestedEyeResolution());
-    nsRefPtr<DOMRect> obj =
-      new DOMRect(mParent,
-                  (aEye == VREye::Left) ? 0 : a.width, 0,
-                  a.width, a.height);
-    return obj.forget();
+    gfx::IntSize sz(mHMD->SuggestedEyeResolution());
+    gfx::VRHMDInfo::Eye eye = aEye == VREye::Left ? gfx::VRHMDInfo::Eye_Left : gfx::VRHMDInfo::Eye_Right;
+    nsRefPtr<VREyeParameters> params =
+      new VREyeParameters(mParent,
+                          gfx::VRFieldOfView(15, 15, 15, 15), // XXX min?
+                          mHMD->GetMaximumEyeFOV(eye),
+                          mHMD->GetRecommendedEyeFOV(eye),
+                          mHMD->GetEyeTranslation(eye),
+                          mHMD->GetEyeFOV(eye),
+                          gfx::IntRect((aEye == VREye::Left) ? 0 : sz.width, 0, sz.width, sz.height));
+    return params.forget();
   }
 
 protected:
-  VRFieldOfView*
-  CopyFieldOfView(const gfx::VRFieldOfView& aSrc)
-  {
-    return new VRFieldOfView(aSrc.upDegrees, aSrc.rightDegrees,
-                             aSrc.downDegrees, aSrc.leftDegrees);
-  }
 };
 
 class HMDPositionVRDevice : public PositionSensorVRDevice
 {
 public:
   HMDPositionVRDevice(nsISupports* aParent, gfx::VRHMDInfo* aHMD)
     : PositionSensorVRDevice(aParent)
     , mHMD(aHMD)
     , mTracking(false)
   {
     // XXX TODO use real names/IDs
-    mHWID.AppendPrintf("HMDInfo-0x%llx", aHMD);
-    mDeviceId.AssignLiteral("somedevid");
-    mDeviceName.AssignLiteral("HMD Position Device");
+    uint64_t hmdid = reinterpret_cast<uint64_t>(aHMD);
+
+    mHWID.Truncate();
+    mHWID.AppendPrintf("HMDInfo-0x%llx", hmdid);
+
+    mDeviceId.Truncate();
+    mDeviceId.AppendPrintf("HMDInfo-dev-0x%llx", hmdid);
+
+    if (aHMD->GetType() == VRHMDType::Oculus) {
+      mDeviceName.AssignLiteral("VR Position Device (oculus)");
+    } else if (aHMD->GetType() == VRHMDType::Cardboard) {
+      mDeviceName.AssignLiteral("VR Position Device (cardboard)");
+    } else {
+      mDeviceName.AssignLiteral("VR Position Device (unknown)");
+    }
 
     mValid = true;
   }
 
   ~HMDPositionVRDevice()
   {
     if (mTracking) {
       mHMD->StopSensorTracking();
     }
   }
 
-  virtual already_AddRefed<VRPositionState> GetState(double timeOffset) override
+  virtual already_AddRefed<VRPositionState> GetState() override
   {
     if (!mTracking) {
       mHMD->StartSensorTracking();
       mTracking = true;
     }
 
-    gfx::VRHMDSensorState state = mHMD->GetSensorState(timeOffset);
+    gfx::VRHMDSensorState state = mHMD->GetSensorState();
     nsRefPtr<VRPositionState> obj = new VRPositionState(mParent, state);
 
     return obj.forget();
   }
 
-  virtual void ZeroSensor() override
+  virtual already_AddRefed<VRPositionState> GetImmediateState() override
+  {
+    if (!mTracking) {
+      mHMD->StartSensorTracking();
+      mTracking = true;
+    }
+
+    gfx::VRHMDSensorState state = mHMD->GetSensorState();
+    nsRefPtr<VRPositionState> obj = new VRPositionState(mParent, state);
+
+    return obj.forget();
+  }
+
+  virtual void ResetSensor() override
   {
     mHMD->ZeroSensor();
   }
 
 protected:
   nsRefPtr<gfx::VRHMDInfo> mHMD;
   bool mTracking;
 };
 
 } // namespace
 
 bool
 VRDevice::CreateAllKnownVRDevices(nsISupports *aParent, nsTArray<nsRefPtr<VRDevice>>& aDevices)
 {
-  if (!gfx::VRHMDManagerOculus::Init()) {
-    NS_WARNING("Failed to initialize Oculus HMD Manager");
-    return false;
-  }
-
   nsTArray<nsRefPtr<gfx::VRHMDInfo>> hmds;
-  gfx::VRHMDManagerOculus::GetOculusHMDs(hmds);
+  gfx::VRHMDManager::GetAllHMDs(hmds);
 
   for (size_t i = 0; i < hmds.Length(); ++i) {
     uint32_t sensorBits = hmds[i]->GetSupportedSensorStateBits();
     aDevices.AppendElement(new HMDInfoVRDevice(aParent, hmds[i]));
 
     if (sensorBits &
         (gfx::VRHMDInfo::State_Position | gfx::VRHMDInfo::State_Orientation))
     {
--- a/dom/vr/VRDevice.h
+++ b/dom/vr/VRDevice.h
@@ -21,71 +21,91 @@
 
 #include "gfxVR.h"
 
 namespace mozilla {
 namespace dom {
 
 class Element;
 
-class VRFieldOfViewReadOnly : public NonRefcountedDOMObject
+class VRFieldOfViewReadOnly : public nsWrapperCache
 {
 public:
-  VRFieldOfViewReadOnly(double aUpDegrees, double aRightDegrees,
+  VRFieldOfViewReadOnly(nsISupports* aParent,
+                        double aUpDegrees, double aRightDegrees,
                         double aDownDegrees, double aLeftDegrees)
-    : mUpDegrees(aUpDegrees)
+    : mParent(aParent)
+    , mUpDegrees(aUpDegrees)
     , mRightDegrees(aRightDegrees)
     , mDownDegrees(aDownDegrees)
     , mLeftDegrees(aLeftDegrees)
   {
   }
 
+  NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(VRFieldOfViewReadOnly)
+  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(VRFieldOfViewReadOnly)
+
   double UpDegrees() const { return mUpDegrees; }
   double RightDegrees() const { return mRightDegrees; }
   double DownDegrees() const { return mDownDegrees; }
   double LeftDegrees() const { return mLeftDegrees; }
 
+  nsISupports* GetParentObject() const { return mParent; }
+  virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
+
 protected:
+  virtual ~VRFieldOfViewReadOnly() {}
+
+  nsCOMPtr<nsISupports> mParent;
+
   double mUpDegrees;
   double mRightDegrees;
   double mDownDegrees;
   double mLeftDegrees;
 };
 
 class VRFieldOfView final : public VRFieldOfViewReadOnly
 {
 public:
-  explicit VRFieldOfView(double aUpDegrees = 0.0, double aRightDegrees = 0.0,
-                         double aDownDegrees = 0.0, double aLeftDegrees = 0.0)
-    : VRFieldOfViewReadOnly(aUpDegrees, aRightDegrees, aDownDegrees, aLeftDegrees)
+  VRFieldOfView(nsISupports* aParent, const gfx::VRFieldOfView& aSrc)
+    : VRFieldOfViewReadOnly(aParent,
+                            aSrc.upDegrees, aSrc.rightDegrees,
+                            aSrc.downDegrees, aSrc.leftDegrees)
   {}
 
-  static VRFieldOfView*
+  explicit VRFieldOfView(nsISupports* aParent,
+                         double aUpDegrees = 0.0, double aRightDegrees = 0.0,
+                         double aDownDegrees = 0.0, double aLeftDegrees = 0.0)
+    : VRFieldOfViewReadOnly(aParent,
+                            aUpDegrees, aRightDegrees, aDownDegrees, aLeftDegrees)
+  {}
+
+  static already_AddRefed<VRFieldOfView>
   Constructor(const GlobalObject& aGlobal, const VRFieldOfViewInit& aParams,
               ErrorResult& aRv);
 
-  static VRFieldOfView*
+  static already_AddRefed<VRFieldOfView>
   Constructor(const GlobalObject& aGlobal,
               double aUpDegrees, double aRightDegrees,
               double aDownDegrees, double aLeftDegrees,
               ErrorResult& aRv);
 
-  bool WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto, JS::MutableHandle<JSObject*> aReflector);
+  virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
 
   void SetUpDegrees(double aVal) { mUpDegrees = aVal; }
   void SetRightDegrees(double aVal) { mRightDegrees = aVal; }
   void SetDownDegrees(double aVal) { mDownDegrees = aVal; }
   void SetLeftDegrees(double aVal) { mLeftDegrees = aVal; }
 };
 
 class VRPositionState final : public nsWrapperCache
 {
   ~VRPositionState() {}
 public:
-  explicit VRPositionState(nsISupports* aParent, const gfx::VRHMDSensorState& aState);
+  VRPositionState(nsISupports* aParent, const gfx::VRHMDSensorState& aState);
 
   NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(VRPositionState)
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(VRPositionState)
 
   double TimeStamp() const { return mTimeStamp; }
 
   bool HasPosition() const { return mPosition != nullptr; }
   DOMPoint* GetPosition() const { return mPosition; }
@@ -112,16 +132,53 @@ protected:
   nsRefPtr<DOMPoint> mLinearVelocity;
   nsRefPtr<DOMPoint> mLinearAcceleration;
 
   nsRefPtr<DOMPoint> mOrientation;
   nsRefPtr<DOMPoint> mAngularVelocity;
   nsRefPtr<DOMPoint> mAngularAcceleration;
 };
 
+class VREyeParameters final : public nsWrapperCache
+{
+public:
+  VREyeParameters(nsISupports* aParent,
+                  const gfx::VRFieldOfView& aMinFOV,
+                  const gfx::VRFieldOfView& aMaxFOV,
+                  const gfx::VRFieldOfView& aRecFOV,
+                  const gfx::Point3D& aEyeTranslation,
+                  const gfx::VRFieldOfView& aCurFOV,
+                  const gfx::IntRect& aRenderRect);
+
+  NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(VREyeParameters)
+  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(VREyeParameters)
+
+  VRFieldOfView* MinimumFieldOfView();
+  VRFieldOfView* MaximumFieldOfView();
+  VRFieldOfView* RecommendedFieldOfView();
+  DOMPoint* EyeTranslation();
+
+  VRFieldOfView* CurrentFieldOfView();
+  DOMRect* RenderRect();
+
+  nsISupports* GetParentObject() const { return mParent; }
+  virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
+protected:
+  ~VREyeParameters() {}
+
+  nsCOMPtr<nsISupports> mParent;
+
+  nsRefPtr<VRFieldOfView> mMinFOV;
+  nsRefPtr<VRFieldOfView> mMaxFOV;
+  nsRefPtr<VRFieldOfView> mRecFOV;
+  nsRefPtr<DOMPoint> mEyeTranslation;
+  nsRefPtr<VRFieldOfView> mCurFOV;
+  nsRefPtr<DOMRect> mRenderRect;
+};
+
 class VRDevice : public nsISupports,
                  public nsWrapperCache
 {
 public:
   // create new VRDevice objects for all known underlying gfx::vr devices
   static bool CreateAllKnownVRDevices(nsISupports *aParent, nsTArray<nsRefPtr<VRDevice>>& aDevices);
 
 public:
@@ -171,49 +228,45 @@ protected:
   VRDeviceType mType;
 
   bool mValid;
 };
 
 class HMDVRDevice : public VRDevice
 {
 public:
-  virtual already_AddRefed<DOMPoint> GetEyeTranslation(VREye aEye) = 0;
+  virtual already_AddRefed<VREyeParameters> GetEyeParameters(VREye aEye) = 0;
 
   virtual void SetFieldOfView(const VRFieldOfViewInit& aLeftFOV,
                               const VRFieldOfViewInit& aRightFOV,
                               double zNear, double zFar) = 0;
-  virtual VRFieldOfView* GetCurrentEyeFieldOfView(VREye aEye) = 0;
-  virtual VRFieldOfView* GetRecommendedEyeFieldOfView(VREye aEye) = 0;
-  virtual VRFieldOfView* GetMaximumEyeFieldOfView(VREye aEye) = 0;
-  virtual already_AddRefed<DOMRect> GetRecommendedEyeRenderRect(VREye aEye) = 0;
 
   virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
 
-  void XxxToggleElementVR(Element& aElement);
-
   gfx::VRHMDInfo *GetHMD() { return mHMD.get(); }
 
 protected:
   HMDVRDevice(nsISupports* aParent, gfx::VRHMDInfo* aHMD)
     : VRDevice(aParent, VRDevice::HMD)
     , mHMD(aHMD)
   { }
 
   virtual ~HMDVRDevice() { }
 
   nsRefPtr<gfx::VRHMDInfo> mHMD;
 };
 
 class PositionSensorVRDevice : public VRDevice
 {
 public:
-  virtual already_AddRefed<VRPositionState> GetState(double timeOffset) = 0;
+  virtual already_AddRefed<VRPositionState> GetState() = 0;
 
-  virtual void ZeroSensor() = 0;
+  virtual already_AddRefed<VRPositionState> GetImmediateState() = 0;
+
+  virtual void ResetSensor() = 0;
 
   virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
 
 protected:
   explicit PositionSensorVRDevice(nsISupports* aParent)
     : VRDevice(aParent, VRDevice::PositionSensor)
   { }
 
--- a/dom/webidl/VRDevice.webidl
+++ b/dom/webidl/VRDevice.webidl
@@ -47,86 +47,84 @@ interface VRPositionState {
 
   readonly attribute boolean hasOrientation;
   // XXX should be DOMQuaternion as soon as we add that
   readonly attribute DOMPoint? orientation;
   readonly attribute DOMPoint? angularVelocity;
   readonly attribute DOMPoint? angularAcceleration;
 };
 
+[Pref="dom.vr.enabled",
+ HeaderFile="mozilla/dom/VRDevice.h"]
+interface VREyeParameters {
+  /* These values are expected to be static per-device/per-user */
+  [Constant, Cached] readonly attribute VRFieldOfView minimumFieldOfView;
+  [Constant, Cached] readonly attribute VRFieldOfView maximumFieldOfView;
+  [Constant, Cached] readonly attribute VRFieldOfView recommendedFieldOfView;
+  [Constant, Cached] readonly attribute DOMPoint eyeTranslation;
+
+  /* These values will vary after a FOV has been set */
+  [Constant, Cached] readonly attribute VRFieldOfView currentFieldOfView;
+  [Constant, Cached] readonly attribute DOMRect renderRect;
+};
+
 [Pref="dom.vr.enabled"]
 interface VRDevice {
   /**
    * An identifier for the distinct hardware unit that this
    * VR Device is a part of.  All VRDevice/Sensors that come
    * from the same hardware will have the same hardwareId
    */
-  [Pure] readonly attribute DOMString hardwareUnitId;
+  [Constant] readonly attribute DOMString hardwareUnitId;
 
   /**
    * An identifier for this distinct sensor/device on a physical
    * hardware device.  This shouldn't change across browser
    * restrats, allowing configuration data to be saved based on it.
    */
-  [Pure] readonly attribute DOMString deviceId;
+  [Constant] readonly attribute DOMString deviceId;
 
   /**
    * a device name, a user-readable name identifying it
    */
-  [Pure] readonly attribute DOMString deviceName;
+  [Constant] readonly attribute DOMString deviceName;
 };
 
 [Pref="dom.vr.enabled",
  HeaderFile="mozilla/dom/VRDevice.h"]
 interface HMDVRDevice : VRDevice {
-  /* The translation that should be applied to the view matrix for rendering each eye */
-  DOMPoint getEyeTranslation(VREye whichEye);
-
-  // the FOV that the HMD was configured with
-  [NewObject]
-  VRFieldOfView getCurrentEyeFieldOfView(VREye whichEye);
-
-  // the recommended FOV, per eye.
-  [NewObject]
-  VRFieldOfView getRecommendedEyeFieldOfView(VREye whichEye);
-
-  // the maximum FOV, per eye.  Above this, rendering will look broken.
-  [NewObject]
-  VRFieldOfView getMaximumEyeFieldOfView(VREye whichEye);
+  // Return the current VREyeParameters for the given eye
+  VREyeParameters getEyeParameters(VREye whichEye);
 
   // Set a field of view.  If either of the fields of view is null,
   // or if their values are all zeros, then the recommended field of view
   // for that eye will be used.
   void setFieldOfView(optional VRFieldOfViewInit leftFOV,
                       optional VRFieldOfViewInit rightFOV,
                       optional double zNear = 0.01,
                       optional double zFar = 10000.0);
-
-  // return a recommended rect for this eye.  Only useful for Canvas rendering,
-  // the x/y coordinates will be the location in the canvas where this eye should
-  // begin, and the width/height are the dimensions.  Any canvas in the appropriate
-  // ratio will work.
-  DOMRect getRecommendedEyeRenderRect(VREye whichEye);
-
-  // hack for testing
-  void xxxToggleElementVR(Element element);
 };
 
 [Pref="dom.vr.enabled" ,
  HeaderFile="mozilla/dom/VRDevice.h"]
 interface PositionSensorVRDevice : VRDevice {
   /*
-   * Return a VRPositionState dictionary containing the state of this position sensor,
-   * at an optional past time or predicted for a future time if timeOffset is != 0.
+   * Return a VRPositionState dictionary containing the state of this position sensor
+   * for the current frame if within a requestAnimationFrame callback, or for the
+   * previous frame if not.
    *
    * The VRPositionState will contain the position, orientation, and velocity
    * and acceleration of each of these properties.  Use "hasPosition" and "hasOrientation"
    * to check if the associated members are valid; if these are false, those members
    * will be null.
    */
-  [NewObject]
-  VRPositionState getState(optional double timeOffset = 0.0);
+  [NewObject] VRPositionState getState();
 
-  /* Zero this sensor, treating its current position and orientation
+  /*
+   * Return the current instantaneous sensor state.
+   */
+  [NewObject] VRPositionState getImmediateState();
+
+  /* Reset this sensor, treating its current position and orientation
    * as the "origin/zero" values.
    */
-  void zeroSensor();
+  void resetSensor();
 };
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -4218,17 +4218,18 @@ private:
 
 NS_IMPL_ISUPPORTS(ReportDebuggerErrorRunnable, nsIRunnable)
 
 WorkerDebugger::WorkerDebugger(WorkerPrivate* aWorkerPrivate)
 : mMutex("WorkerDebugger::mMutex"),
   mCondVar(mMutex, "WorkerDebugger::mCondVar"),
   mWorkerPrivate(aWorkerPrivate),
   mIsEnabled(false),
-  mIsInitialized(false)
+  mIsInitialized(false),
+  mIsFrozen(false)
 {
   mWorkerPrivate->AssertIsOnParentThread();
 }
 
 WorkerDebugger::~WorkerDebugger()
 {
   MOZ_ASSERT(!mWorkerPrivate);
   MOZ_ASSERT(!mIsEnabled);
@@ -4273,16 +4274,31 @@ WorkerDebugger::GetIsChrome(bool* aResul
     return NS_ERROR_UNEXPECTED;
   }
 
   *aResult = mWorkerPrivate->IsChromeWorker();
   return NS_OK;
 }
 
 NS_IMETHODIMP
+WorkerDebugger::GetIsFrozen(bool* aResult)
+{
+  AssertIsOnMainThread();
+
+  MutexAutoLock lock(mMutex);
+
+  if (!mWorkerPrivate) {
+    return NS_ERROR_UNEXPECTED;
+  }
+
+  *aResult = mIsFrozen;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 WorkerDebugger::GetParent(nsIWorkerDebugger** aResult)
 {
   AssertIsOnMainThread();
 
   MutexAutoLock lock(mMutex);
 
   if (!mWorkerPrivate) {
     return NS_ERROR_UNEXPECTED;
@@ -4470,16 +4486,62 @@ WorkerDebugger::Disable()
       listeners[index]->OnClose();
     }
   }
 
   NotifyIsEnabled(false);
 }
 
 void
+WorkerDebugger::Freeze()
+{
+  mWorkerPrivate->AssertIsOnWorkerThread();
+
+  nsCOMPtr<nsIRunnable> runnable =
+    NS_NewRunnableMethod(this, &WorkerDebugger::FreezeOnMainThread);
+  MOZ_ALWAYS_TRUE(NS_SUCCEEDED(
+    NS_DispatchToMainThread(runnable, NS_DISPATCH_NORMAL)));
+}
+
+void
+WorkerDebugger::FreezeOnMainThread()
+{
+  AssertIsOnMainThread();
+
+  mIsFrozen = true;
+
+  for (size_t index = 0; index < mListeners.Length(); ++index) {
+    mListeners[index]->OnFreeze();
+  }
+}
+
+void
+WorkerDebugger::Thaw()
+{
+  mWorkerPrivate->AssertIsOnWorkerThread();
+
+  nsCOMPtr<nsIRunnable> runnable =
+    NS_NewRunnableMethod(this, &WorkerDebugger::ThawOnMainThread);
+  MOZ_ALWAYS_TRUE(NS_SUCCEEDED(
+    NS_DispatchToMainThread(runnable, NS_DISPATCH_NORMAL)));
+}
+
+void
+WorkerDebugger::ThawOnMainThread()
+{
+  AssertIsOnMainThread();
+
+  mIsFrozen = false;
+
+  for (size_t index = 0; index < mListeners.Length(); ++index) {
+    mListeners[index]->OnThaw();
+  }
+}
+
+void
 WorkerDebugger::PostMessageToDebugger(const nsAString& aMessage)
 {
   mWorkerPrivate->AssertIsOnWorkerThread();
 
   nsCOMPtr<nsIRunnable> runnable =
     NS_NewRunnableMethodWithArg<nsString>(this,
       &WorkerDebugger::PostMessageToDebuggerOnMainThread, nsString(aMessage));
   NS_DispatchToMainThread(runnable, NS_DISPATCH_NORMAL);
@@ -5688,27 +5750,29 @@ WorkerPrivate::RemainingRunTimeMS() cons
 bool
 WorkerPrivate::FreezeInternal(JSContext* aCx)
 {
   AssertIsOnWorkerThread();
 
   NS_ASSERTION(!mFrozen, "Already frozen!");
 
   mFrozen = true;
+  mDebugger->Freeze();
   return true;
 }
 
 bool
 WorkerPrivate::ThawInternal(JSContext* aCx)
 {
   AssertIsOnWorkerThread();
 
   NS_ASSERTION(mFrozen, "Not yet frozen!");
 
   mFrozen = false;
+  mDebugger->Thaw();
   return true;
 }
 
 void
 WorkerPrivate::TraceTimeouts(const TraceCallbacks& aCallbacks,
                              void* aClosure) const
 {
   AssertIsOnWorkerThread();
--- a/dom/workers/WorkerPrivate.h
+++ b/dom/workers/WorkerPrivate.h
@@ -722,16 +722,17 @@ class WorkerDebugger : public nsIWorkerD
   mozilla::CondVar mCondVar;
 
   // Protected by mMutex
   WorkerPrivate* mWorkerPrivate;
   bool mIsEnabled;
 
   // Only touched on the main thread.
   bool mIsInitialized;
+  bool mIsFrozen;
   nsTArray<nsCOMPtr<nsIWorkerDebuggerListener>> mListeners;
 
 public:
   explicit WorkerDebugger(WorkerPrivate* aWorkerPrivate);
 
   NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIWORKERDEBUGGER
 
@@ -743,30 +744,42 @@ public:
 
   void
   Enable();
 
   void
   Disable();
 
   void
+  Freeze();
+
+  void
+  Thaw();
+
+  void
   PostMessageToDebugger(const nsAString& aMessage);
 
   void
   ReportErrorToDebugger(const nsAString& aFilename, uint32_t aLineno,
                         const nsAString& aMessage);
 
 private:
   virtual
   ~WorkerDebugger();
 
   void
   NotifyIsEnabled(bool aIsEnabled);
 
   void
+  FreezeOnMainThread();
+
+  void
+  ThawOnMainThread();
+
+  void
   PostMessageToDebuggerOnMainThread(const nsAString& aMessage);
 
   void
   ReportErrorToDebuggerOnMainThread(const nsAString& aFilename,
                                     uint32_t aLineno,
                                     const nsAString& aMessage);
 };
 
--- a/dom/workers/nsIWorkerDebugger.idl
+++ b/dom/workers/nsIWorkerDebugger.idl
@@ -1,34 +1,40 @@
 #include "nsISupports.idl"
 
 interface nsIDOMWindow;
 
-[scriptable, uuid(55d54034-1573-4889-b1d9-93ba12fc33c7)]
+[scriptable, uuid(530db841-1b2c-485a-beeb-f2b1acb9714e)]
 interface nsIWorkerDebuggerListener : nsISupports
 {
   void onClose();
 
   void onError(in DOMString filename, in unsigned long lineno,
                in DOMString message);
 
+  void onFreeze();
+
   void onMessage(in DOMString message);
+
+  void onThaw();
 };
 
-[scriptable, builtinclass, uuid(28e0a60c-ff10-446c-8c2a-5fbdc01394ea)]
+[scriptable, builtinclass, uuid(d7c73e54-3c41-4393-9d13-fa2ed4Ba6764)]
 interface nsIWorkerDebugger : nsISupports
 {
   const unsigned long TYPE_DEDICATED = 0;
   const unsigned long TYPE_SHARED = 1;
   const unsigned long TYPE_SERVICE = 2;
 
   readonly attribute bool isClosed;
 
   readonly attribute bool isChrome;
 
+  readonly attribute bool isFrozen;
+
   readonly attribute nsIWorkerDebugger parent;
 
   readonly attribute unsigned long type;
 
   readonly attribute DOMString url;
 
   readonly attribute nsIDOMWindow window;
 
new file mode 100644
--- /dev/null
+++ b/dom/workers/test/WorkerDebugger.isFrozen_iframe1.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <meta charset="utf-8">
+    <script>
+      var worker = new Worker("WorkerDebugger.isFrozen_worker1.js");
+      worker.onmessage = function () {
+        parent.postMessage("ready", "*");
+      };
+    </script>
+  </head>
+  <body>
+    This is page 1.
+  </body>
+<html>
new file mode 100644
--- /dev/null
+++ b/dom/workers/test/WorkerDebugger.isFrozen_iframe2.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <meta charset="utf-8">
+    <script>
+      var worker = new Worker("WorkerDebugger.isFrozen_worker2.js");
+      worker.onmessage = function () {
+        parent.postMessage("ready", "*");
+      };
+    </script>
+  </head>
+  <body>
+    This is page 2.
+  </body>
+<html>
new file mode 100644
--- /dev/null
+++ b/dom/workers/test/WorkerDebugger.isFrozen_worker1.js
@@ -0,0 +1,5 @@
+"use strict";
+
+onmessage = function () {};
+
+postMessage("ready");
new file mode 100644
--- /dev/null
+++ b/dom/workers/test/WorkerDebugger.isFrozen_worker2.js
@@ -0,0 +1,5 @@
+"use strict";
+
+onmessage = function () {};
+
+postMessage("ready");
--- a/dom/workers/test/chrome.ini
+++ b/dom/workers/test/chrome.ini
@@ -1,14 +1,18 @@
 [DEFAULT]
 skip-if = buildapp == 'b2g'
 support-files =
   WorkerDebugger.initialize_childWorker.js
   WorkerDebugger.initialize_debugger.js
   WorkerDebugger.initialize_worker.js
+  WorkerDebugger.isFrozen_iframe1.html
+  WorkerDebugger.isFrozen_iframe2.html
+  WorkerDebugger.isFrozen_worker1.js
+  WorkerDebugger.isFrozen_worker2.js
   WorkerDebugger.postMessage_childWorker.js
   WorkerDebugger.postMessage_debugger.js
   WorkerDebugger.postMessage_worker.js
   WorkerDebuggerGlobalScope.createSandbox_debugger.js
   WorkerDebuggerGlobalScope.createSandbox_sandbox.js
   WorkerDebuggerGlobalScope.createSandbox_worker.js
   WorkerDebuggerGlobalScope.enterEventLoop_childWorker.js
   WorkerDebuggerGlobalScope.enterEventLoop_debugger.js
@@ -42,16 +46,17 @@ support-files =
   file_worker.js
   jsm_url_worker.js
   workersDisabled_worker.js
   file_url.jsm
   bug1062920_worker.js
 
 [test_WorkerDebugger.xul]
 [test_WorkerDebugger.initialize.xul]
+[test_WorkerDebugger.isFrozen.xul]
 [test_WorkerDebugger.postMessage.xul]
 [test_WorkerDebuggerGlobalScope.createSandbox.xul]
 [test_WorkerDebuggerGlobalScope.enterEventLoop.xul]
 [test_WorkerDebuggerGlobalScope.reportError.xul]
 [test_WorkerDebuggerGlobalScope.setImmediate.xul]
 [test_WorkerDebuggerManager.xul]
 [test_bug883784.jsm]
 [test_bug883784.xul]
--- a/dom/workers/test/dom_worker_helper.js
+++ b/dom/workers/test/dom_worker_helper.js
@@ -125,16 +125,51 @@ function waitForDebuggerMessage(dbg, mes
         ok(true, "Should receive " + message + " message from debugger.");
         dbg.removeListener(this);
         resolve();
       }
     });
   });
 }
 
+function waitForDebuggerFreeze(dbg) {
+  return new Promise(function (resolve) {
+    dbg.addListener({
+      onFreeze: function () {
+        dbg.removeListener(this);
+        resolve();
+      }
+    });
+  });
+}
+
+function waitForDebuggerThaw(dbg) {
+  return new Promise(function (resolve) {
+    dbg.addListener({
+      onThaw: function () {
+        dbg.removeListener(this);
+        resolve();
+      }
+    });
+  });
+}
+
+function waitForWindowMessage(window, message) {
+  return new Promise(function (resolve) {
+    let onmessage = function (event) {
+      if (event.data !== event.data) {
+        return;
+      }
+      window.removeEventListener("message", onmessage, false);
+      resolve();
+    };
+    window.addEventListener("message", onmessage, false);
+  });
+}
+
 function waitForWorkerMessage(worker, message) {
   return new Promise(function (resolve) {
     worker.addEventListener("message", function onmessage(event) {
       if (event.data !== message) {
         return;
       }
       ok(true, "Should receive " + message + " message from worker.");
       worker.removeEventListener("message", onmessage);
new file mode 100644
--- /dev/null
+++ b/dom/workers/test/test_WorkerDebugger.isFrozen.xul
@@ -0,0 +1,98 @@
+<?xml version="1.0"?>
+<!--
+  Any copyright is dedicated to the Public Domain.
+  http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<window title="Test for WorkerDebugger.isFrozen"
+        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+        onload="test();">
+
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/>
+  <script type="application/javascript" src="dom_worker_helper.js"/>
+
+  <script type="application/javascript">
+  <![CDATA[
+
+    const CACHE_SUBFRAMES = "browser.sessionhistory.cache_subframes";
+    const MAX_TOTAL_VIEWERS = "browser.sessionhistory.max_total_viewers";
+
+    const IFRAME1_URL = "WorkerDebugger.isFrozen_iframe1.html";
+    const IFRAME2_URL = "WorkerDebugger.isFrozen_iframe2.html";
+
+    const WORKER1_URL = "WorkerDebugger.isFrozen_worker1.js";
+    const WORKER2_URL = "WorkerDebugger.isFrozen_worker2.js";
+
+    function test() {
+      Task.spawn(function* () {
+        SimpleTest.waitForExplicitFinish();
+
+        var oldMaxTotalViewers = SpecialPowers.getIntPref(MAX_TOTAL_VIEWERS);
+
+        SpecialPowers.setBoolPref(CACHE_SUBFRAMES, true);
+        SpecialPowers.setIntPref(MAX_TOTAL_VIEWERS, 10);
+
+        let iframe = $("iframe");
+
+        let promise = waitForMultiple([
+          waitForRegister(WORKER1_URL),
+          waitForWindowMessage(window, "ready"),
+        ]);
+        iframe.src = IFRAME1_URL;
+        let [dbg1] = yield promise;
+        is(dbg1.isClosed, false,
+           "debugger for worker on page 1 should not be closed");
+        is(dbg1.isFrozen, false,
+           "debugger for worker on page 1 should not be frozen");
+
+        promise = waitForMultiple([
+          waitForDebuggerFreeze(dbg1),
+          waitForRegister(WORKER2_URL),
+          waitForWindowMessage(window, "ready"),
+        ]);
+        iframe.src = IFRAME2_URL;
+        let [_, dbg2] = yield promise;
+        is(dbg1.isClosed, false,
+           "debugger for worker on page 1 should not be closed");
+        is(dbg1.isFrozen, true,
+           "debugger for worker on page 1 should be frozen");
+        is(dbg2.isClosed, false,
+           "debugger for worker on page 2 should not be closed");
+        is(dbg2.isFrozen, false,
+           "debugger for worker on page 2 should not be frozen");
+
+        promise = waitForMultiple([
+          waitForDebuggerFreeze(dbg2),
+          waitForDebuggerThaw(dbg1),
+        ]);
+        iframe.contentWindow.history.back();
+        yield promise;
+        is(dbg1.isClosed, false,
+           "debugger for worker on page 1 should not be closed")
+        is(dbg1.isFrozen, false,
+           "debugger for worker on page 1 should not be frozen");
+        is(dbg2.isClosed, false,
+           "debugger for worker on page 2 should not be closed");
+        is(dbg2.isFrozen, true,
+           "debugger for worker on page 2 should be frozen");
+
+        SpecialPowers.clearUserPref(CACHE_SUBFRAMES);
+        SpecialPowers.setIntPref(MAX_TOTAL_VIEWERS, oldMaxTotalViewers);
+
+        SimpleTest.finish();
+      });
+    }
+
+  ]]>
+  </script>
+
+  <body xmlns="http://www.w3.org/1999/xhtml">
+    <p id="display"></p>
+    <div id="content" style="display:none;"></div>
+    <pre id="test"></pre>
+    <iframe id="iframe"></iframe>
+  </body>
+  <label id="test-result"/>
+</window>
--- a/embedding/browser/nsDocShellTreeOwner.cpp
+++ b/embedding/browser/nsDocShellTreeOwner.cpp
@@ -1447,19 +1447,25 @@ ChromeTooltipListener::sTooltipCallback(
       bool textFound = false;
 
       self->mTooltipTextProvider->GetNodeText(
           self->mPossibleTooltipNode, getter_Copies(tooltipText), &textFound);
 
       if (textFound) {
         nsString tipText(tooltipText);
         LayoutDeviceIntPoint screenDot = widget->WidgetToScreenOffset();
-        self->ShowTooltip(self->mMouseScreenX - screenDot.x,
-                          self->mMouseScreenY - screenDot.y,
-                          tipText);
+        double scaleFactor = 1.0;
+        if (shell->GetPresContext()) {
+          scaleFactor = double(nsPresContext::AppUnitsPerCSSPixel())/
+          shell->GetPresContext()->DeviceContext()->AppUnitsPerDevPixelAtUnitFullZoom();
+        }
+        // ShowTooltip expects widget-relative position.
+        self->ShowTooltip(self->mMouseScreenX - screenDot.x / scaleFactor,
+          self->mMouseScreenY - screenDot.y / scaleFactor,
+          tipText);
       }
     }
 
     // release tooltip target if there is one, NO MATTER WHAT
     self->mPossibleTooltipNode = nullptr;
   } // if "self" data valid
 
 } // sTooltipCallback
--- a/gfx/2d/2D.h
+++ b/gfx/2d/2D.h
@@ -5,16 +5,17 @@
 
 #ifndef _MOZILLA_GFX_2D_H
 #define _MOZILLA_GFX_2D_H
 
 #include "Types.h"
 #include "Point.h"
 #include "Rect.h"
 #include "Matrix.h"
+#include "Quaternion.h"
 #include "UserData.h"
 
 // GenericRefCountedBase allows us to hold on to refcounted objects of any type
 // (contrary to RefCounted<T> which requires knowing the type T) and, in particular,
 // without having a dependency on that type. This is used for DrawTargetSkia
 // to be able to hold on to a GLContext.
 #include "mozilla/GenericRefCounted.h"
 
--- a/gfx/2d/Matrix.cpp
+++ b/gfx/2d/Matrix.cpp
@@ -1,14 +1,15 @@
 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "Matrix.h"
+#include "Quaternion.h"
 #include "Tools.h"
 #include <algorithm>
 #include <ostream>
 #include <math.h>
 
 #include "mozilla/FloatingPoint.h" // for UnspecifiedNaN
 
 using namespace std;
@@ -23,16 +24,27 @@ operator<<(std::ostream& aStream, const 
                  << " "  << aMatrix._12
                  << "; " << aMatrix._21
                  << " "  << aMatrix._22
                  << "; " << aMatrix._31
                  << " "  << aMatrix._32
                  << "; ]";
 }
 
+std::ostream&
+operator<<(std::ostream& aStream, const Matrix4x4& aMatrix)
+{
+  const Float *f = &aMatrix._11;
+  aStream << "[ " << f[0] << " "  << f[1] << " " << f[2] << " " << f[3] << " ;" << std::endl; f += 4;
+  aStream << "  " << f[0] << " "  << f[1] << " " << f[2] << " " << f[3] << " ;" << std::endl; f += 4;
+  aStream << "  " << f[0] << " "  << f[1] << " " << f[2] << " " << f[3] << " ;" << std::endl; f += 4;
+  aStream << "  " << f[0] << " "  << f[1] << " " << f[2] << " " << f[3] << " ]" << std::endl;
+  return aStream;
+}
+
 Matrix
 Matrix::Rotation(Float aAngle)
 {
   Matrix newMatrix;
 
   Float s = sin(aAngle);
   Float c = cos(aAngle);
 
@@ -278,10 +290,37 @@ Matrix4x4::SetNAN()
   _33 = UnspecifiedNaN<Float>();
   _43 = UnspecifiedNaN<Float>();
   _14 = UnspecifiedNaN<Float>();
   _24 = UnspecifiedNaN<Float>();
   _34 = UnspecifiedNaN<Float>();
   _44 = UnspecifiedNaN<Float>();
 }
 
+void
+Matrix4x4::SetRotationFromQuaternion(const Quaternion& q)
+{
+  const Float x2 = q.x + q.x, y2 = q.y + q.y, z2 = q.z + q.z;
+  const Float xx = q.x * x2, xy = q.x * y2, xz = q.x * z2;
+  const Float yy = q.y * y2, yz = q.y * z2, zz = q.z * z2;
+  const Float wx = q.w * x2, wy = q.w * y2, wz = q.w * z2;
+
+  _11 = 1.0f - (yy + zz);
+  _21 = xy + wz;
+  _31 = xz - wy;
+  _41 = 0.0f;
+
+  _12 = xy - wz;
+  _22 = 1.0f - (xx + zz);
+  _32 = yz + wx;
+  _42 = 0.0f;
+
+  _13 = xz + wy;
+  _23 = yz - wx;
+  _33 = 1.0f - (xx + yy);
+  _43 = 0.0f;
+
+  _14 = _42 = _43 = 0.0f;
+  _44 = 1.0f;
+}
+
 }
 }
--- a/gfx/2d/Matrix.h
+++ b/gfx/2d/Matrix.h
@@ -12,16 +12,18 @@
 #include <iosfwd>
 #include <math.h>
 #include "mozilla/Attributes.h"
 #include "mozilla/DebugOnly.h"
 
 namespace mozilla {
 namespace gfx {
 
+class Quaternion;
+
 static bool FuzzyEqual(Float aV1, Float aV2) {
   // XXX - Check if fabs does the smart thing and just negates the sign bit.
   return fabs(aV2 - aV1) < 1e-6;
 }
 
 class Matrix
 {
 public:
@@ -385,16 +387,18 @@ public:
     memcpy(this, &aOther, sizeof(*this));
   }
 
   Float _11, _12, _13, _14;
   Float _21, _22, _23, _24;
   Float _31, _32, _33, _34;
   Float _41, _42, _43, _44;
 
+  friend std::ostream& operator<<(std::ostream& aStream, const Matrix4x4& aMatrix);
+
   Point4D& operator[](int aIndex)
   {
       MOZ_ASSERT(aIndex >= 0 && aIndex <= 3, "Invalid matrix array index");
       return *reinterpret_cast<Point4D*>((&_11)+4*aIndex);
   }
   const Point4D& operator[](int aIndex) const
   {
       MOZ_ASSERT(aIndex >= 0 && aIndex <= 3, "Invalid matrix array index");
@@ -867,16 +871,21 @@ public:
   {
       MOZ_ASSERT(aIndex >= 0 && aIndex <= 3, "Invalid matrix array index");
       *((&_11)+aIndex) = aVector.x;
       *((&_21)+aIndex) = aVector.y;
       *((&_31)+aIndex) = aVector.z;
       *((&_41)+aIndex) = aVector.w;
   }
 
+  // Sets this matrix to a rotation matrix given by aQuat.
+  // This quaternion *MUST* be normalized!
+  // Implemented in Quaternion.cpp
+  void SetRotationFromQuaternion(const Quaternion& aQuat);
+
   // Set all the members of the matrix to NaN
   void SetNAN();
 };
 
 class Matrix5x4
 {
 public:
   Matrix5x4()
new file mode 100644
--- /dev/null
+++ b/gfx/2d/Quaternion.cpp
@@ -0,0 +1,57 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "Quaternion.h"
+#include "Matrix.h"
+#include "Tools.h"
+#include <algorithm>
+#include <ostream>
+#include <math.h>
+
+using namespace std;
+
+namespace mozilla {
+namespace gfx {
+
+std::ostream&
+operator<<(std::ostream& aStream, const Quaternion& aQuat)
+{
+  return aStream << "< " << aQuat.x << " "  << aQuat.y << " " << aQuat.z << " " << aQuat.w << ">";
+}
+
+void
+Quaternion::SetFromRotationMatrix(const Matrix4x4& m)
+{
+  // see http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm
+  const Float trace = m._11 + m._22 + m._33;
+  if (trace > 0.0) {
+    const Float s = 0.5f / sqrt(trace + 1.0f);
+    w = 0.25f / s;
+    x = (m._32 - m._23) * s;
+    y = (m._13 - m._31) * s;
+    z = (m._21 - m._12) * s;
+  } else if (m._11 > m._22 && m._11 > m._33) {
+    const Float s = 2.0f * sqrt(1.0f + m._11 - m._22 - m._33);
+    w = (m._32 - m._23) / s;
+    x = 0.25f * s;
+    y = (m._12 + m._21) / s;
+    z = (m._13 + m._31) / s;
+  } else if (m._22 > m._33) {
+    const Float s = 2.0 * sqrt(1.0f + m._22 - m._11 - m._33);
+    w = (m._13 - m._31) / s;
+    x = (m._12 + m._21) / s;
+    y = 0.25f * s;
+    z = (m._23 + m._32) / s;
+  } else {
+    const Float s = 2.0 * sqrt(1.0f + m._33 - m._11 - m._22);
+    w = (m._21 - m._12) / s;
+    x = (m._13 + m._31) / s;
+    y = (m._23 + m._32) / s;
+    z = 0.25f * s;
+  }
+}
+
+}
+}
new file mode 100644
--- /dev/null
+++ b/gfx/2d/Quaternion.h
@@ -0,0 +1,100 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef MOZILLA_GFX_QUATERNION_H_
+#define MOZILLA_GFX_QUATERNION_H_
+
+#include "Types.h"
+#include <math.h>
+#include "mozilla/Attributes.h"
+#include "mozilla/DebugOnly.h"
+
+namespace mozilla {
+namespace gfx {
+
+class Matrix4x4;
+
+class Quaternion
+{
+public:
+  Quaternion()
+    : x(0.0f), y(0.0f), z(0.0f), w(1.0f)
+  {}
+
+  Quaternion(Float aX, Float aY, Float aZ, Float aW)
+    : x(aX), y(aY), z(aZ), w(aW)
+  {}
+
+
+  Quaternion(const Quaternion& aOther)
+  {
+    memcpy(this, &aOther, sizeof(*this));
+  }
+
+  Float x, y, z, w;
+
+  friend std::ostream& operator<<(std::ostream& aStream, const Quaternion& aQuat);
+
+  void Set(Float aX, Float aY, Float aZ, Float aW)
+  {
+    x = aX; y = aY; z = aZ; w = aW;
+  }
+
+  // Assumes upper 3x3 of aMatrix is a pure rotation matrix (no scaling)
+  void SetFromRotationMatrix(const Matrix4x4& aMatrix);
+
+  // result = this * aQuat
+  Quaternion operator*(const Quaternion &aQuat) const
+  {
+    Quaternion o;
+    const Float bx = aQuat.x, by = aQuat.y, bz = aQuat.z, bw = aQuat.w;
+
+    o.x = x*bw + w*bx + y*bz - z*by;
+    o.y = y*bw + w*by + z*bx - x*bz;
+    o.z = z*bw + w*bz + x*by - y*bx;
+    o.w = w*bw - x*bx - y*by - z*bz;
+    return o;
+  }
+
+  Quaternion& operator*=(const Quaternion &aQuat)
+  {
+    *this = *this * aQuat;
+    return *this;
+  }
+
+  Float Length() const
+  {
+    return sqrt(x*x + y*y + z*z + w*w);
+  }
+
+  Quaternion& Conjugate()
+  {
+    x *= -1.f; y *= -1.f; z *= -1.f;
+    return *this;
+  }
+
+  Quaternion& Normalize()
+  {
+    Float l = Length();
+    if (l) {
+      l = 1.0f / l;
+      x *= l; y *= l; z *= l; w *= l;
+    } else {
+      x = y = z = 0.f;
+      w = 1.f;
+    }
+    return *this;
+  }
+
+  Quaternion& Invert()
+  {
+    return Conjugate().Normalize();
+  }
+};
+
+}
+}
+
+#endif
--- a/gfx/2d/moz.build
+++ b/gfx/2d/moz.build
@@ -24,16 +24,17 @@ EXPORTS.mozilla.gfx += [
     'DrawTargetTiled.h',
     'Filters.h',
     'Helpers.h',
     'Logging.h',
     'Matrix.h',
     'PathHelpers.h',
     'PatternHelpers.h',
     'Point.h',
+    'Quaternion.h',
     'Rect.h',
     'Scale.h',
     'ScaleFactor.h',
     'ScaleFactors2D.h',
     'SourceSurfaceCairo.h',
     'Tools.h',
     'Types.h',
     'UserData.h',
@@ -115,16 +116,17 @@ UNIFIED_SOURCES += [
     'FilterNodeSoftware.cpp',
     'FilterProcessing.cpp',
     'FilterProcessingScalar.cpp',
     'ImageScaling.cpp',
     'Matrix.cpp',
     'Path.cpp',
     'PathCairo.cpp',
     'PathRecording.cpp',
+    'Quaternion.cpp',
     'RecordedEvent.cpp',
     'Scale.cpp',
     'ScaledFontBase.cpp',
     'ScaledFontCairo.cpp',
     'SourceSurfaceCairo.cpp',
     'SourceSurfaceRawData.cpp',
 ]
 
--- a/gfx/layers/d3d11/CompositorD3D11.cpp
+++ b/gfx/layers/d3d11/CompositorD3D11.cpp
@@ -68,27 +68,29 @@ struct DeviceAttachmentsD3D11
   RefPtr<ID3D11BlendState> mNonPremulBlendState;
   RefPtr<ID3D11BlendState> mComponentBlendState;
   RefPtr<ID3D11BlendState> mDisabledBlendState;
   RefPtr<IDXGIResource> mSyncTexture;
 
   //
   // VR pieces
   //
-  RefPtr<ID3D11InputLayout> mVRDistortionInputLayout;
-  RefPtr<ID3D11Buffer> mVRDistortionConstants;
-
+  typedef EnumeratedArray<VRHMDType, VRHMDType::NumHMDTypes, RefPtr<ID3D11InputLayout>>
+          VRDistortionInputLayoutArray;
   typedef EnumeratedArray<VRHMDType, VRHMDType::NumHMDTypes, RefPtr<ID3D11VertexShader>>
           VRVertexShaderArray;
   typedef EnumeratedArray<VRHMDType, VRHMDType::NumHMDTypes, RefPtr<ID3D11PixelShader>>
           VRPixelShaderArray;
 
+  VRDistortionInputLayoutArray mVRDistortionInputLayout;
   VRVertexShaderArray mVRDistortionVS;
   VRPixelShaderArray mVRDistortionPS;
 
+  RefPtr<ID3D11Buffer> mVRDistortionConstants;
+
   // These will be created/filled in as needed during rendering whenever the configuration
   // changes.
   VRHMDConfiguration mVRConfiguration;
   RefPtr<ID3D11Buffer> mVRDistortionVertices[2]; // one for each eye
   RefPtr<ID3D11Buffer> mVRDistortionIndices[2];
   uint32_t mVRDistortionIndexCount[2];
 };
 
@@ -329,17 +331,22 @@ CompositorD3D11::Initialize()
       { "TEXCOORD", 2, DXGI_FORMAT_R32G32_FLOAT,       0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
       { "COLOR",    0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
     };
 
     hr = mDevice->CreateInputLayout(vrlayout,
                                     sizeof(vrlayout) / sizeof(D3D11_INPUT_ELEMENT_DESC),
                                     OculusVRDistortionVS,
                                     sizeof(OculusVRDistortionVS),
-                                    byRef(mAttachments->mVRDistortionInputLayout));
+                                    byRef(mAttachments->mVRDistortionInputLayout[VRHMDType::Oculus]));
+
+    // XXX shared for now, rename
+    mAttachments->mVRDistortionInputLayout[VRHMDType::Cardboard] =
+      mAttachments->mVRDistortionInputLayout[VRHMDType::Oculus];
+
     cBufferDesc.ByteWidth = sizeof(gfx::VRDistortionConstants);
     hr = mDevice->CreateBuffer(&cBufferDesc, nullptr, byRef(mAttachments->mVRDistortionConstants));
     if (FAILED(hr)) {
       return false;
     }
   }
 
   nsRefPtr<IDXGIDevice> dxgiDevice;
@@ -656,16 +663,17 @@ CompositorD3D11::DrawVRDistortion(const 
 
   EffectVRDistortion* vrEffect =
     static_cast<EffectVRDistortion*>(aEffectChain.mPrimaryEffect.get());
 
   TextureSourceD3D11* source = vrEffect->mTexture->AsSourceD3D11();
   gfx::IntSize size = vrEffect->mRenderTarget->GetSize(); // XXX source->GetSize()
 
   VRHMDInfo* hmdInfo = vrEffect->mHMD;
+  VRHMDType hmdType = hmdInfo->GetType();
   VRDistortionConstants shaderConstants;
 
   // do we need to recreate the VR buffers, since the config has changed?
   if (hmdInfo->GetConfiguration() != mAttachments->mVRConfiguration) {
     D3D11_SUBRESOURCE_DATA sdata = { 0 };
     CD3D11_BUFFER_DESC desc(0, D3D11_BIND_VERTEX_BUFFER, D3D11_USAGE_IMMUTABLE);
 
     // XXX as an optimization, we should really pack the indices and vertices for both eyes
@@ -704,30 +712,27 @@ CompositorD3D11::DrawVRDistortion(const 
   scissor.left = aClipRect.x;
   scissor.right = aClipRect.XMost();
   scissor.top = aClipRect.y;
   scissor.bottom = aClipRect.YMost();
   mContext->RSSetScissorRects(1, &scissor);
 
   // Triangle lists and same layout for both eyes
   mContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
-  mContext->IASetInputLayout(mAttachments->mVRDistortionInputLayout);
-
-  // Shaders for this HMD
-  mContext->VSSetShader(mAttachments->mVRDistortionVS[mAttachments->mVRConfiguration.hmdType], nullptr, 0);
-  mContext->PSSetShader(mAttachments->mVRDistortionPS[mAttachments->mVRConfiguration.hmdType], nullptr, 0);
+  mContext->IASetInputLayout(mAttachments->mVRDistortionInputLayout[hmdType]);
+  mContext->VSSetShader(mAttachments->mVRDistortionVS[hmdType], nullptr, 0);
+  mContext->PSSetShader(mAttachments->mVRDistortionPS[hmdType], nullptr, 0);
 
   // This is the source texture SRV for the pixel shader
-  // XXX, um should we cache this SRV?
+  // XXX, um should we cache this SRV on the source?
   RefPtr<ID3D11ShaderResourceView> view;
   mDevice->CreateShaderResourceView(source->GetD3D11Texture(), nullptr, byRef(view));
   ID3D11ShaderResourceView* srView = view;
   mContext->PSSetShaderResources(0, 1, &srView);
 
-
   gfx::IntSize vpSizeInt = mCurrentRT->GetSize();
   gfx::Size vpSize(vpSizeInt.width, vpSizeInt.height);
   ID3D11Buffer* vbuffer;
   UINT vsize, voffset;
 
   for (uint32_t eye = 0; eye < 2; eye++) {
     gfx::IntRect eyeViewport;
     eyeViewport.x = eye * size.width / 2;
@@ -1338,16 +1343,21 @@ CompositorD3D11::CreateShaders()
   hr = mDevice->CreatePixelShader(OculusVRDistortionPS,
                                   sizeof(OculusVRDistortionPS),
                                   nullptr,
                                   byRef(mAttachments->mVRDistortionPS[VRHMDType::Oculus]));
   if (FAILED(hr)) {
     return false;
   }
 
+  // These are shared
+  // XXX rename Oculus shaders to something more generic
+  mAttachments->mVRDistortionVS[VRHMDType::Cardboard] = mAttachments->mVRDistortionVS[VRHMDType::Oculus];
+  mAttachments->mVRDistortionPS[VRHMDType::Cardboard] = mAttachments->mVRDistortionPS[VRHMDType::Oculus];
+
   return true;
 }
 
 bool
 CompositorD3D11::UpdateConstantBuffers()
 {
   HRESULT hr;
   D3D11_MAPPED_SUBRESOURCE resource;
--- a/gfx/layers/d3d11/CompositorD3D11Shaders.h
+++ b/gfx/layers/d3d11/CompositorD3D11Shaders.h
@@ -1,14 +1,13 @@
 #if 0
 //
-// Generated by Microsoft (R) HLSL Shader Compiler 9.30.9200.20546
-//
-//
-///
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
 // Buffer Definitions: 
 //
 // cbuffer $Globals
 // {
 //
 //   float4x4 mLayerTransform;          // Offset:    0 Size:    64
 //   float4x4 mProjection;              // Offset:   64 Size:    64
 //   float4 vRenderTargetOffset;        // Offset:  128 Size:    16
@@ -99,20 +98,20 @@ mad r1.xyzw, cb0[6].xyzw, r0.zzzz, r1.xy
 mad o0.xyzw, cb0[7].xyzw, r0.wwww, r1.xyzw
 mad o1.xy, v0.xyxx, cb0[9].zwzz, cb0[9].xyxx
 ret 
 // Approximately 13 instruction slots used
 #endif
 
 const BYTE LayerQuadVS[] =
 {
-     68,  88,  66,  67,  67,  61, 
-     27, 151,  57,  33,  48,  19, 
-     55,   6,  95,  77, 254, 163, 
-    118, 237,   1,   0,   0,   0, 
+     68,  88,  66,  67, 200, 251, 
+     64, 251, 166, 240, 101, 137, 
+    191, 140,  75, 217,   9, 168, 
+     61, 163,   1,   0,   0,   0, 
     180,   6,   0,   0,   6,   0, 
       0,   0,  56,   0,   0,   0, 
     152,   1,   0,   0, 160,   3, 
       0,   0,  28,   4,   0,   0, 
      40,   6,   0,   0,  92,   6, 
       0,   0,  65, 111, 110,  57, 
      88,   1,   0,   0,  88,   1, 
       0,   0,   0,   2, 254, 255, 
@@ -257,27 +256,27 @@ const BYTE LayerQuadVS[] =
     230, 138,  32,   0,   0,   0, 
       0,   0,   9,   0,   0,   0, 
      70, 128,  32,   0,   0,   0, 
       0,   0,   9,   0,   0,   0, 
      62,   0,   0,   1,  83,  84, 
      65,  84, 116,   0,   0,   0, 
      13,   0,   0,   0,   2,   0, 
       0,   0,   0,   0,   0,   0, 
-      3,   0,   0,   0,   6,   0, 
+      3,   0,   0,   0,  12,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   1,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   2,   0, 
+      0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,  82,  68,  69,  70, 
       4,   2,   0,   0,   1,   0, 
@@ -358,20 +357,20 @@ const BYTE LayerQuadVS[] =
       0, 171,   0,   0,   3,   0, 
       1,   0,   1,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
      77, 105,  99, 114, 111, 115, 
     111, 102, 116,  32,  40,  82, 
      41,  32,  72,  76,  83,  76, 
      32,  83, 104,  97, 100, 101, 
     114,  32,  67, 111, 109, 112, 
-    105, 108, 101, 114,  32,  57, 
-     46,  51,  48,  46,  57,  50, 
-     48,  48,  46,  50,  48,  53, 
-     52,  54,   0, 171,  73,  83, 
+    105, 108, 101, 114,  32,  54, 
+     46,  51,  46,  57,  54,  48, 
+     48,  46,  49,  54,  51,  56, 
+     52,   0, 171, 171,  73,  83, 
      71,  78,  44,   0,   0,   0, 
       1,   0,   0,   0,   8,   0, 
       0,   0,  32,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   3,   0,   0,   0, 
       0,   0,   0,   0,   3,   3, 
       0,   0,  80,  79,  83,  73, 
      84,  73,  79,  78,   0, 171, 
@@ -388,20 +387,19 @@ const BYTE LayerQuadVS[] =
       0,   0,   3,  12,   0,   0, 
      83,  86,  95,  80, 111, 115, 
     105, 116, 105, 111, 110,   0, 
      84,  69,  88,  67,  79,  79, 
      82,  68,   0, 171, 171, 171
 };
 #if 0
 //
-// Generated by Microsoft (R) HLSL Shader Compiler 9.30.9200.20546
-//
-//
-///
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
 // Buffer Definitions: 
 //
 // cbuffer $Globals
 // {
 //
 //   float4 fLayerColor;                // Offset:    0 Size:    16
 //   float fLayerOpacity;               // Offset:   16 Size:     4 [unused]
 //   float4x4 mLayerTransform;          // Offset:   32 Size:    64 [unused]
@@ -455,20 +453,20 @@ dcl_constantbuffer cb0[1], immediateInde
 dcl_output o0.xyzw
 mov o0.xyzw, cb0[0].xyzw
 ret 
 // Approximately 2 instruction slots used
 #endif
 
 const BYTE SolidColorShader[] =
 {
-     68,  88,  66,  67, 182,  98, 
-    102, 100, 187, 218,  19,  40, 
-     99,  74,  29, 228,  47, 107, 
-    160, 122,   1,   0,   0,   0, 
+     68,  88,  66,  67,  30, 148, 
+    104, 202, 165,  39,  58, 182, 
+    100, 205,  95, 195,  52, 137, 
+    197, 241,   1,   0,   0,   0, 
     224,   3,   0,   0,   6,   0, 
       0,   0,  56,   0,   0,   0, 
     132,   0,   0,   0, 204,   0, 
       0,   0,  72,   1,   0,   0, 
      84,   3,   0,   0, 172,   3, 
       0,   0,  65, 111, 110,  57, 
      68,   0,   0,   0,  68,   0, 
       0,   0,   0,   2, 255, 255, 
@@ -503,17 +501,17 @@ const BYTE SolidColorShader[] =
       1,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
-      2,   0,   0,   0,   0,   0, 
+      1,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,  82,  68, 
      69,  70,   4,   2,   0,   0, 
       1,   0,   0,   0,  72,   0, 
@@ -594,19 +592,19 @@ const BYTE SolidColorShader[] =
      81, 117,  97, 100,   0, 118, 
      77,  97, 115, 107,  81, 117, 
      97, 100,   0,  77, 105,  99, 
     114, 111, 115, 111, 102, 116, 
      32,  40,  82,  41,  32,  72, 
      76,  83,  76,  32,  83, 104, 
      97, 100, 101, 114,  32,  67, 
     111, 109, 112, 105, 108, 101, 
-    114,  32,  57,  46,  51,  48, 
-     46,  57,  50,  48,  48,  46, 
-     50,  48,  53,  52,  54,   0, 
+    114,  32,  54,  46,  51,  46, 
+     57,  54,  48,  48,  46,  49, 
+     54,  51,  56,  52,   0, 171, 
      73,  83,  71,  78,  80,   0, 
       0,   0,   2,   0,   0,   0, 
       8,   0,   0,   0,  56,   0, 
       0,   0,   0,   0,   0,   0, 
       1,   0,   0,   0,   3,   0, 
       0,   0,   0,   0,   0,   0, 
      15,   0,   0,   0,  68,   0, 
       0,   0,   0,   0,   0,   0, 
@@ -624,20 +622,19 @@ const BYTE SolidColorShader[] =
       0,   0,   3,   0,   0,   0, 
       0,   0,   0,   0,  15,   0, 
       0,   0,  83,  86,  95,  84, 
      97, 114, 103, 101, 116,   0, 
     171, 171
 };
 #if 0
 //
-// Generated by Microsoft (R) HLSL Shader Compiler 9.30.9200.20546
-//
-//
-///
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
 // Buffer Definitions: 
 //
 // cbuffer $Globals
 // {
 //
 //   float4 fLayerColor;                // Offset:    0 Size:    16 [unused]
 //   float fLayerOpacity;               // Offset:   16 Size:     4
 //   float4x4 mLayerTransform;          // Offset:   32 Size:    64 [unused]
@@ -711,20 +708,20 @@ sample r0.xyzw, v1.xyxx, t0.xyzw, s0
 mul o0.xyz, r0.xyzx, cb0[1].xxxx
 mov o0.w, cb0[1].x
 ret 
 // Approximately 4 instruction slots used
 #endif
 
 const BYTE RGBShader[] =
 {
-     68,  88,  66,  67, 195,  54, 
-    227,  44,  79, 159, 121,  69, 
-     60, 252, 145,  90, 151, 241, 
-    175, 162,   1,   0,   0,   0, 
+     68,  88,  66,  67, 239, 198, 
+     87, 206,  69,  92, 245,  30, 
+    125, 195, 239,  77,  37, 241, 
+    175, 187,   1,   0,   0,   0, 
     232,   4,   0,   0,   6,   0, 
       0,   0,  56,   0,   0,   0, 
     204,   0,   0,   0, 136,   1, 
       0,   0,   4,   2,   0,   0, 
      92,   4,   0,   0, 180,   4, 
       0,   0,  65, 111, 110,  57, 
     140,   0,   0,   0, 140,   0, 
       0,   0,   0,   2, 255, 255, 
@@ -790,308 +787,16 @@ const BYTE RGBShader[] =
       0,   0,   1,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       1,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
-      0,   0,   2,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-     82,  68,  69,  70,  80,   2, 
-      0,   0,   1,   0,   0,   0, 
-    148,   0,   0,   0,   3,   0, 
-      0,   0,  28,   0,   0,   0, 
-      0,   4, 255, 255,   0,   1, 
-      0,   0,  29,   2,   0,   0, 
-    124,   0,   0,   0,   3,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      1,   0,   0,   0,   1,   0, 
-      0,   0, 133,   0,   0,   0, 
-      2,   0,   0,   0,   5,   0, 
-      0,   0,   4,   0,   0,   0, 
-    255, 255, 255, 255,   0,   0, 
-      0,   0,   1,   0,   0,   0, 
-     12,   0,   0,   0, 138,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   1,   0, 
-      0,   0,   0,   0,   0,   0, 
-    115,  83,  97, 109, 112, 108, 
-    101, 114,   0, 116,  82,  71, 
-     66,   0,  36,  71, 108, 111, 
-     98,  97, 108, 115,   0, 171, 
-    138,   0,   0,   0,   8,   0, 
-      0,   0, 172,   0,   0,   0, 
-    224,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-    108,   1,   0,   0,   0,   0, 
-      0,   0,  16,   0,   0,   0, 
-      0,   0,   0,   0, 120,   1, 
-      0,   0,   0,   0,   0,   0, 
-    136,   1,   0,   0,  16,   0, 
-      0,   0,   4,   0,   0,   0, 
-      2,   0,   0,   0, 152,   1, 
-      0,   0,   0,   0,   0,   0, 
-    168,   1,   0,   0,  32,   0, 
-      0,   0,  64,   0,   0,   0, 
-      0,   0,   0,   0, 184,   1, 
-      0,   0,   0,   0,   0,   0, 
-    200,   1,   0,   0,  96,   0, 
-      0,   0,  64,   0,   0,   0, 
-      0,   0,   0,   0, 184,   1, 
-      0,   0,   0,   0,   0,   0, 
-    212,   1,   0,   0, 160,   0, 
-      0,   0,  16,   0,   0,   0, 
-      0,   0,   0,   0, 120,   1, 
-      0,   0,   0,   0,   0,   0, 
-    232,   1,   0,   0, 176,   0, 
-      0,   0,  16,   0,   0,   0, 
-      0,   0,   0,   0, 248,   1, 
-      0,   0,   0,   0,   0,   0, 
-      8,   2,   0,   0, 192,   0, 
-      0,   0,  16,   0,   0,   0, 
-      0,   0,   0,   0, 248,   1, 
-      0,   0,   0,   0,   0,   0, 
-     19,   2,   0,   0, 208,   0, 
-      0,   0,  16,   0,   0,   0, 
-      0,   0,   0,   0, 248,   1, 
-      0,   0,   0,   0,   0,   0, 
-    102,  76,  97, 121, 101, 114, 
-     67, 111, 108, 111, 114,   0, 
-      1,   0,   3,   0,   1,   0, 
-      4,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0, 102,  76, 
-     97, 121, 101, 114,  79, 112, 
-     97,  99, 105, 116, 121,   0, 
-    171, 171,   0,   0,   3,   0, 
-      1,   0,   1,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-    109,  76,  97, 121, 101, 114, 
-     84, 114,  97, 110, 115, 102, 
-    111, 114, 109,   0,   3,   0, 
-      3,   0,   4,   0,   4,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0, 109,  80, 114, 111, 
-    106, 101,  99, 116, 105, 111, 
-    110,   0, 118,  82, 101, 110, 
-    100, 101, 114,  84,  97, 114, 
-    103, 101, 116,  79, 102, 102, 
-    115, 101, 116,   0, 118,  84, 
-    101, 120, 116, 117, 114, 101, 
-     67, 111, 111, 114, 100, 115, 
-      0, 171,   1,   0,   3,   0, 
-      1,   0,   4,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-    118,  76,  97, 121, 101, 114, 
-     81, 117,  97, 100,   0, 118, 
-     77,  97, 115, 107,  81, 117, 
-     97, 100,   0,  77, 105,  99, 
-    114, 111, 115, 111, 102, 116, 
-     32,  40,  82,  41,  32,  72, 
-     76,  83,  76,  32,  83, 104, 
-     97, 100, 101, 114,  32,  67, 
-    111, 109, 112, 105, 108, 101, 
-    114,  32,  57,  46,  51,  48, 
-     46,  57,  50,  48,  48,  46, 
-     50,  48,  53,  52,  54,   0, 
-     73,  83,  71,  78,  80,   0, 
-      0,   0,   2,   0,   0,   0, 
-      8,   0,   0,   0,  56,   0, 
-      0,   0,   0,   0,   0,   0, 
-      1,   0,   0,   0,   3,   0, 
-      0,   0,   0,   0,   0,   0, 
-     15,   0,   0,   0,  68,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   3,   0, 
-      0,   0,   1,   0,   0,   0, 
-      3,   3,   0,   0,  83,  86, 
-     95,  80, 111, 115, 105, 116, 
-    105, 111, 110,   0,  84,  69, 
-     88,  67,  79,  79,  82,  68, 
-      0, 171, 171, 171,  79,  83, 
-     71,  78,  44,   0,   0,   0, 
-      1,   0,   0,   0,   8,   0, 
-      0,   0,  32,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   3,   0,   0,   0, 
-      0,   0,   0,   0,  15,   0, 
-      0,   0,  83,  86,  95,  84, 
-     97, 114, 103, 101, 116,   0, 
-    171, 171
-};
-#if 0
-//
-// Generated by Microsoft (R) HLSL Shader Compiler 9.30.9200.20546
-//
-//
-///
-// Buffer Definitions: 
-//
-// cbuffer $Globals
-// {
-//
-//   float4 fLayerColor;                // Offset:    0 Size:    16 [unused]
-//   float fLayerOpacity;               // Offset:   16 Size:     4
-//   float4x4 mLayerTransform;          // Offset:   32 Size:    64 [unused]
-//   float4x4 mProjection;              // Offset:   96 Size:    64 [unused]
-//   float4 vRenderTargetOffset;        // Offset:  160 Size:    16 [unused]
-//   float4 vTextureCoords;             // Offset:  176 Size:    16 [unused]
-//   float4 vLayerQuad;                 // Offset:  192 Size:    16 [unused]
-//   float4 vMaskQuad;                  // Offset:  208 Size:    16 [unused]
-//
-// }
-//
-//
-// Resource Bindings:
-//
-// Name                                 Type  Format         Dim Slot Elements
-// ------------------------------ ---------- ------- ----------- ---- --------
-// sSampler                          sampler      NA          NA    0        1
-// tRGB                              texture  float4          2d    0        1
-// $Globals                          cbuffer      NA          NA    0        1
-//
-//
-//
-// Input signature:
-//
-// Name                 Index   Mask Register SysValue  Format   Used
-// -------------------- ----- ------ -------- -------- ------- ------
-// SV_Position              0   xyzw        0      POS   float       
-// TEXCOORD                 0   xy          1     NONE   float   xy  
-//
-//
-// Output signature:
-//
-// Name                 Index   Mask Register SysValue  Format   Used
-// -------------------- ----- ------ -------- -------- ------- ------
-// SV_Target                0   xyzw        0   TARGET   float   xyzw
-//
-//
-// Constant buffer to DX9 shader constant mappings:
-//
-// Target Reg Buffer  Start Reg # of Regs        Data Conversion
-// ---------- ------- --------- --------- ----------------------
-// c0         cb0             1         1  ( FLT, FLT, FLT, FLT)
-//
-//
-// Sampler/Resource to DX9 shader sampler mappings:
-//
-// Target Sampler Source Sampler  Source Resource
-// -------------- --------------- ----------------
-// s0             s0              t0               
-//
-//
-// Level9 shader bytecode:
-//
-    ps_2_x
-    dcl t0.xy
-    dcl_2d s0
-    texld r0, t0, s0
-    mul r0, r0, c0.x
-    mov oC0, r0
-
-// approximately 3 instruction slots used (1 texture, 2 arithmetic)
-ps_4_0
-dcl_constantbuffer cb0[2], immediateIndexed
-dcl_sampler s0, mode_default
-dcl_resource_texture2d (float,float,float,float) t0
-dcl_input_ps linear v1.xy
-dcl_output o0.xyzw
-dcl_temps 1
-sample r0.xyzw, v1.xyxx, t0.xyzw, s0
-mul o0.xyzw, r0.xyzw, cb0[1].xxxx
-ret 
-// Approximately 3 instruction slots used
-#endif
-
-const BYTE RGBAShader[] =
-{
-     68,  88,  66,  67, 124,  18, 
-      8, 218,  34, 168,  20, 218, 
-    144, 232, 183, 104, 152, 211, 
-      5,  26,   1,   0,   0,   0, 
-    196,   4,   0,   0,   6,   0, 
-      0,   0,  56,   0,   0,   0, 
-    192,   0,   0,   0, 100,   1, 
-      0,   0, 224,   1,   0,   0, 
-     56,   4,   0,   0, 144,   4, 
-      0,   0,  65, 111, 110,  57, 
-    128,   0,   0,   0, 128,   0, 
-      0,   0,   0,   2, 255, 255, 
-     76,   0,   0,   0,  52,   0, 
-      0,   0,   1,   0,  40,   0, 
-      0,   0,  52,   0,   0,   0, 
-     52,   0,   1,   0,  36,   0, 
-      0,   0,  52,   0,   0,   0, 
-      0,   0,   0,   0,   1,   0, 
-      1,   0,   0,   0,   0,   0, 
-      0,   0,   1,   2, 255, 255, 
-     31,   0,   0,   2,   0,   0, 
-      0, 128,   0,   0,   3, 176, 
-     31,   0,   0,   2,   0,   0, 
-      0, 144,   0,   8,  15, 160, 
-     66,   0,   0,   3,   0,   0, 
-     15, 128,   0,   0, 228, 176, 
-      0,   8, 228, 160,   5,   0, 
-      0,   3,   0,   0,  15, 128, 
-      0,   0, 228, 128,   0,   0, 
-      0, 160,   1,   0,   0,   2, 
-      0,   8,  15, 128,   0,   0, 
-    228, 128, 255, 255,   0,   0, 
-     83,  72,  68,  82, 156,   0, 
-      0,   0,  64,   0,   0,   0, 
-     39,   0,   0,   0,  89,   0, 
-      0,   4,  70, 142,  32,   0, 
-      0,   0,   0,   0,   2,   0, 
-      0,   0,  90,   0,   0,   3, 
-      0,  96,  16,   0,   0,   0, 
-      0,   0,  88,  24,   0,   4, 
-      0, 112,  16,   0,   0,   0, 
-      0,   0,  85,  85,   0,   0, 
-     98,  16,   0,   3,  50,  16, 
-     16,   0,   1,   0,   0,   0, 
-    101,   0,   0,   3, 242,  32, 
-     16,   0,   0,   0,   0,   0, 
-    104,   0,   0,   2,   1,   0, 
-      0,   0,  69,   0,   0,   9, 
-    242,   0,  16,   0,   0,   0, 
-      0,   0,  70,  16,  16,   0, 
-      1,   0,   0,   0,  70, 126, 
-     16,   0,   0,   0,   0,   0, 
-      0,  96,  16,   0,   0,   0, 
-      0,   0,  56,   0,   0,   8, 
-    242,  32,  16,   0,   0,   0, 
-      0,   0,  70,  14,  16,   0, 
-      0,   0,   0,   0,   6, 128, 
-     32,   0,   0,   0,   0,   0, 
-      1,   0,   0,   0,  62,   0, 
-      0,   1,  83,  84,  65,  84, 
-    116,   0,   0,   0,   3,   0, 
-      0,   0,   1,   0,   0,   0, 
-      0,   0,   0,   0,   2,   0, 
-      0,   0,   1,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   1,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      1,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
       0,   0,   1,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
      82,  68,  69,  70,  80,   2, 
@@ -1186,19 +891,19 @@ const BYTE RGBAShader[] =
      81, 117,  97, 100,   0, 118, 
      77,  97, 115, 107,  81, 117, 
      97, 100,   0,  77, 105,  99, 
     114, 111, 115, 111, 102, 116, 
      32,  40,  82,  41,  32,  72, 
      76,  83,  76,  32,  83, 104, 
      97, 100, 101, 114,  32,  67, 
     111, 109, 112, 105, 108, 101, 
-    114,  32,  57,  46,  51,  48, 
-     46,  57,  50,  48,  48,  46, 
-     50,  48,  53,  52,  54,   0, 
+    114,  32,  54,  46,  51,  46, 
+     57,  54,  48,  48,  46,  49, 
+     54,  51,  56,  52,   0, 171, 
      73,  83,  71,  78,  80,   0, 
       0,   0,   2,   0,   0,   0, 
       8,   0,   0,   0,  56,   0, 
       0,   0,   0,   0,   0,   0, 
       1,   0,   0,   0,   3,   0, 
       0,   0,   0,   0,   0,   0, 
      15,   0,   0,   0,  68,   0, 
       0,   0,   0,   0,   0,   0, 
@@ -1216,20 +921,310 @@ const BYTE RGBAShader[] =
       0,   0,   3,   0,   0,   0, 
       0,   0,   0,   0,  15,   0, 
       0,   0,  83,  86,  95,  84, 
      97, 114, 103, 101, 116,   0, 
     171, 171
 };
 #if 0
 //
-// Generated by Microsoft (R) HLSL Shader Compiler 9.30.9200.20546
-//
-//
-///
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Buffer Definitions: 
+//
+// cbuffer $Globals
+// {
+//
+//   float4 fLayerColor;                // Offset:    0 Size:    16 [unused]
+//   float fLayerOpacity;               // Offset:   16 Size:     4
+//   float4x4 mLayerTransform;          // Offset:   32 Size:    64 [unused]
+//   float4x4 mProjection;              // Offset:   96 Size:    64 [unused]
+//   float4 vRenderTargetOffset;        // Offset:  160 Size:    16 [unused]
+//   float4 vTextureCoords;             // Offset:  176 Size:    16 [unused]
+//   float4 vLayerQuad;                 // Offset:  192 Size:    16 [unused]
+//   float4 vMaskQuad;                  // Offset:  208 Size:    16 [unused]
+//
+// }
+//
+//
+// Resource Bindings:
+//
+// Name                                 Type  Format         Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// sSampler                          sampler      NA          NA    0        1
+// tRGB                              texture  float4          2d    0        1
+// $Globals                          cbuffer      NA          NA    0        1
+//
+//
+//
+// Input signature:
+//
+// Name                 Index   Mask Register SysValue  Format   Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_Position              0   xyzw        0      POS   float       
+// TEXCOORD                 0   xy          1     NONE   float   xy  
+//
+//
+// Output signature:
+//
+// Name                 Index   Mask Register SysValue  Format   Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_Target                0   xyzw        0   TARGET   float   xyzw
+//
+//
+// Constant buffer to DX9 shader constant mappings:
+//
+// Target Reg Buffer  Start Reg # of Regs        Data Conversion
+// ---------- ------- --------- --------- ----------------------
+// c0         cb0             1         1  ( FLT, FLT, FLT, FLT)
+//
+//
+// Sampler/Resource to DX9 shader sampler mappings:
+//
+// Target Sampler Source Sampler  Source Resource
+// -------------- --------------- ----------------
+// s0             s0              t0               
+//
+//
+// Level9 shader bytecode:
+//
+    ps_2_x
+    dcl t0.xy
+    dcl_2d s0
+    texld r0, t0, s0
+    mul r0, r0, c0.x
+    mov oC0, r0
+
+// approximately 3 instruction slots used (1 texture, 2 arithmetic)
+ps_4_0
+dcl_constantbuffer cb0[2], immediateIndexed
+dcl_sampler s0, mode_default
+dcl_resource_texture2d (float,float,float,float) t0
+dcl_input_ps linear v1.xy
+dcl_output o0.xyzw
+dcl_temps 1
+sample r0.xyzw, v1.xyxx, t0.xyzw, s0
+mul o0.xyzw, r0.xyzw, cb0[1].xxxx
+ret 
+// Approximately 3 instruction slots used
+#endif
+
+const BYTE RGBAShader[] =
+{
+     68,  88,  66,  67, 230,  59, 
+     90,  23,  60,  77,  18, 113, 
+     14, 129, 183, 152, 233,  55, 
+    111,  42,   1,   0,   0,   0, 
+    196,   4,   0,   0,   6,   0, 
+      0,   0,  56,   0,   0,   0, 
+    192,   0,   0,   0, 100,   1, 
+      0,   0, 224,   1,   0,   0, 
+     56,   4,   0,   0, 144,   4, 
+      0,   0,  65, 111, 110,  57, 
+    128,   0,   0,   0, 128,   0, 
+      0,   0,   0,   2, 255, 255, 
+     76,   0,   0,   0,  52,   0, 
+      0,   0,   1,   0,  40,   0, 
+      0,   0,  52,   0,   0,   0, 
+     52,   0,   1,   0,  36,   0, 
+      0,   0,  52,   0,   0,   0, 
+      0,   0,   0,   0,   1,   0, 
+      1,   0,   0,   0,   0,   0, 
+      0,   0,   1,   2, 255, 255, 
+     31,   0,   0,   2,   0,   0, 
+      0, 128,   0,   0,   3, 176, 
+     31,   0,   0,   2,   0,   0, 
+      0, 144,   0,   8,  15, 160, 
+     66,   0,   0,   3,   0,   0, 
+     15, 128,   0,   0, 228, 176, 
+      0,   8, 228, 160,   5,   0, 
+      0,   3,   0,   0,  15, 128, 
+      0,   0, 228, 128,   0,   0, 
+      0, 160,   1,   0,   0,   2, 
+      0,   8,  15, 128,   0,   0, 
+    228, 128, 255, 255,   0,   0, 
+     83,  72,  68,  82, 156,   0, 
+      0,   0,  64,   0,   0,   0, 
+     39,   0,   0,   0,  89,   0, 
+      0,   4,  70, 142,  32,   0, 
+      0,   0,   0,   0,   2,   0, 
+      0,   0,  90,   0,   0,   3, 
+      0,  96,  16,   0,   0,   0, 
+      0,   0,  88,  24,   0,   4, 
+      0, 112,  16,   0,   0,   0, 
+      0,   0,  85,  85,   0,   0, 
+     98,  16,   0,   3,  50,  16, 
+     16,   0,   1,   0,   0,   0, 
+    101,   0,   0,   3, 242,  32, 
+     16,   0,   0,   0,   0,   0, 
+    104,   0,   0,   2,   1,   0, 
+      0,   0,  69,   0,   0,   9, 
+    242,   0,  16,   0,   0,   0, 
+      0,   0,  70,  16,  16,   0, 
+      1,   0,   0,   0,  70, 126, 
+     16,   0,   0,   0,   0,   0, 
+      0,  96,  16,   0,   0,   0, 
+      0,   0,  56,   0,   0,   8, 
+    242,  32,  16,   0,   0,   0, 
+      0,   0,  70,  14,  16,   0, 
+      0,   0,   0,   0,   6, 128, 
+     32,   0,   0,   0,   0,   0, 
+      1,   0,   0,   0,  62,   0, 
+      0,   1,  83,  84,  65,  84, 
+    116,   0,   0,   0,   3,   0, 
+      0,   0,   1,   0,   0,   0, 
+      0,   0,   0,   0,   2,   0, 
+      0,   0,   1,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   1,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      1,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+     82,  68,  69,  70,  80,   2, 
+      0,   0,   1,   0,   0,   0, 
+    148,   0,   0,   0,   3,   0, 
+      0,   0,  28,   0,   0,   0, 
+      0,   4, 255, 255,   0,   1, 
+      0,   0,  29,   2,   0,   0, 
+    124,   0,   0,   0,   3,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      1,   0,   0,   0,   1,   0, 
+      0,   0, 133,   0,   0,   0, 
+      2,   0,   0,   0,   5,   0, 
+      0,   0,   4,   0,   0,   0, 
+    255, 255, 255, 255,   0,   0, 
+      0,   0,   1,   0,   0,   0, 
+     12,   0,   0,   0, 138,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   1,   0, 
+      0,   0,   0,   0,   0,   0, 
+    115,  83,  97, 109, 112, 108, 
+    101, 114,   0, 116,  82,  71, 
+     66,   0,  36,  71, 108, 111, 
+     98,  97, 108, 115,   0, 171, 
+    138,   0,   0,   0,   8,   0, 
+      0,   0, 172,   0,   0,   0, 
+    224,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+    108,   1,   0,   0,   0,   0, 
+      0,   0,  16,   0,   0,   0, 
+      0,   0,   0,   0, 120,   1, 
+      0,   0,   0,   0,   0,   0, 
+    136,   1,   0,   0,  16,   0, 
+      0,   0,   4,   0,   0,   0, 
+      2,   0,   0,   0, 152,   1, 
+      0,   0,   0,   0,   0,   0, 
+    168,   1,   0,   0,  32,   0, 
+      0,   0,  64,   0,   0,   0, 
+      0,   0,   0,   0, 184,   1, 
+      0,   0,   0,   0,   0,   0, 
+    200,   1,   0,   0,  96,   0, 
+      0,   0,  64,   0,   0,   0, 
+      0,   0,   0,   0, 184,   1, 
+      0,   0,   0,   0,   0,   0, 
+    212,   1,   0,   0, 160,   0, 
+      0,   0,  16,   0,   0,   0, 
+      0,   0,   0,   0, 120,   1, 
+      0,   0,   0,   0,   0,   0, 
+    232,   1,   0,   0, 176,   0, 
+      0,   0,  16,   0,   0,   0, 
+      0,   0,   0,   0, 248,   1, 
+      0,   0,   0,   0,   0,   0, 
+      8,   2,   0,   0, 192,   0, 
+      0,   0,  16,   0,   0,   0, 
+      0,   0,   0,   0, 248,   1, 
+      0,   0,   0,   0,   0,   0, 
+     19,   2,   0,   0, 208,   0, 
+      0,   0,  16,   0,   0,   0, 
+      0,   0,   0,   0, 248,   1, 
+      0,   0,   0,   0,   0,   0, 
+    102,  76,  97, 121, 101, 114, 
+     67, 111, 108, 111, 114,   0, 
+      1,   0,   3,   0,   1,   0, 
+      4,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0, 102,  76, 
+     97, 121, 101, 114,  79, 112, 
+     97,  99, 105, 116, 121,   0, 
+    171, 171,   0,   0,   3,   0, 
+      1,   0,   1,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+    109,  76,  97, 121, 101, 114, 
+     84, 114,  97, 110, 115, 102, 
+    111, 114, 109,   0,   3,   0, 
+      3,   0,   4,   0,   4,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0, 109,  80, 114, 111, 
+    106, 101,  99, 116, 105, 111, 
+    110,   0, 118,  82, 101, 110, 
+    100, 101, 114,  84,  97, 114, 
+    103, 101, 116,  79, 102, 102, 
+    115, 101, 116,   0, 118,  84, 
+    101, 120, 116, 117, 114, 101, 
+     67, 111, 111, 114, 100, 115, 
+      0, 171,   1,   0,   3,   0, 
+      1,   0,   4,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+    118,  76,  97, 121, 101, 114, 
+     81, 117,  97, 100,   0, 118, 
+     77,  97, 115, 107,  81, 117, 
+     97, 100,   0,  77, 105,  99, 
+    114, 111, 115, 111, 102, 116, 
+     32,  40,  82,  41,  32,  72, 
+     76,  83,  76,  32,  83, 104, 
+     97, 100, 101, 114,  32,  67, 
+    111, 109, 112, 105, 108, 101, 
+    114,  32,  54,  46,  51,  46, 
+     57,  54,  48,  48,  46,  49, 
+     54,  51,  56,  52,   0, 171, 
+     73,  83,  71,  78,  80,   0, 
+      0,   0,   2,   0,   0,   0, 
+      8,   0,   0,   0,  56,   0, 
+      0,   0,   0,   0,   0,   0, 
+      1,   0,   0,   0,   3,   0, 
+      0,   0,   0,   0,   0,   0, 
+     15,   0,   0,   0,  68,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   3,   0, 
+      0,   0,   1,   0,   0,   0, 
+      3,   3,   0,   0,  83,  86, 
+     95,  80, 111, 115, 105, 116, 
+    105, 111, 110,   0,  84,  69, 
+     88,  67,  79,  79,  82,  68, 
+      0, 171, 171, 171,  79,  83, 
+     71,  78,  44,   0,   0,   0, 
+      1,   0,   0,   0,   8,   0, 
+      0,   0,  32,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   3,   0,   0,   0, 
+      0,   0,   0,   0,  15,   0, 
+      0,   0,  83,  86,  95,  84, 
+     97, 114, 103, 101, 116,   0, 
+    171, 171
+};
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
 // Buffer Definitions: 
 //
 // cbuffer $Globals
 // {
 //
 //   float4 fLayerColor;                // Offset:    0 Size:    16 [unused]
 //   float fLayerOpacity;               // Offset:   16 Size:     4
 //   float4x4 mLayerTransform;          // Offset:   32 Size:    64 [unused]
@@ -1319,20 +1314,20 @@ mov r1.w, r0.y
 mul o1.xyzw, r0.xyzw, cb0[1].xxxx
 mul o0.xyzw, r1.xyzw, cb0[1].xxxx
 ret 
 // Approximately 8 instruction slots used
 #endif
 
 const BYTE ComponentAlphaShader[] =
 {
-     68,  88,  66,  67, 152,  37, 
-    117,  77,  87, 153,  20,  62, 
-     92, 142,  77, 134, 246, 203, 
-    174,  59,   1,   0,   0,   0, 
+     68,  88,  66,  67, 186, 162, 
+     72,  42,  69,  36, 160,  68, 
+    108, 121, 216, 238, 108,  37, 
+      6, 145,   1,   0,   0,   0, 
      68,   6,   0,   0,   6,   0, 
       0,   0,  56,   0,   0,   0, 
      64,   1,   0,   0, 160,   2, 
       0,   0,  28,   3,   0,   0, 
     160,   5,   0,   0, 248,   5, 
       0,   0,  65, 111, 110,  57, 
       0,   1,   0,   0,   0,   1, 
       0,   0,   0,   2, 255, 255, 
@@ -1445,17 +1440,17 @@ const BYTE ComponentAlphaShader[] =
       1,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   2,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
-      3,   0,   0,   0,   0,   0, 
+      1,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,  82,  68, 
      69,  70, 124,   2,   0,   0, 
       1,   0,   0,   0, 192,   0, 
@@ -1556,19 +1551,19 @@ const BYTE ComponentAlphaShader[] =
      81, 117,  97, 100,   0, 118, 
      77,  97, 115, 107,  81, 117, 
      97, 100,   0,  77, 105,  99, 
     114, 111, 115, 111, 102, 116, 
      32,  40,  82,  41,  32,  72, 
      76,  83,  76,  32,  83, 104, 
      97, 100, 101, 114,  32,  67, 
     111, 109, 112, 105, 108, 101, 
-    114,  32,  57,  46,  51,  48, 
-     46,  57,  50,  48,  48,  46, 
-     50,  48,  53,  52,  54,   0, 
+    114,  32,  54,  46,  51,  46, 
+     57,  54,  48,  48,  46,  49, 
+     54,  51,  56,  52,   0, 171, 
      73,  83,  71,  78,  80,   0, 
       0,   0,   2,   0,   0,   0, 
       8,   0,   0,   0,  56,   0, 
       0,   0,   0,   0,   0,   0, 
       1,   0,   0,   0,   3,   0, 
       0,   0,   0,   0,   0,   0, 
      15,   0,   0,   0,  68,   0, 
       0,   0,   0,   0,   0,   0, 
@@ -1590,20 +1585,19 @@ const BYTE ComponentAlphaShader[] =
       0,   0,   3,   0,   0,   0, 
       1,   0,   0,   0,  15,   0, 
       0,   0,  83,  86,  95,  84, 
      97, 114, 103, 101, 116,   0, 
     171, 171
 };
 #if 0
 //
-// Generated by Microsoft (R) HLSL Shader Compiler 9.30.9200.20546
-//
-//
-///
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
 // Buffer Definitions: 
 //
 // cbuffer $Globals
 // {
 //
 //   float4 fLayerColor;                // Offset:    0 Size:    16 [unused]
 //   float fLayerOpacity;               // Offset:   16 Size:     4
 //   float4x4 mLayerTransform;          // Offset:   32 Size:    64 [unused]
@@ -1709,20 +1703,20 @@ mad r1.z, r0.z, l(1.164380), r0.x
 mov r1.w, l(1.000000)
 mul o0.xyzw, r1.xyzw, cb0[1].xxxx
 ret 
 // Approximately 15 instruction slots used
 #endif
 
 const BYTE YCbCrShader[] =
 {
-     68,  88,  66,  67,  26, 187, 
-     43, 127,  28, 135, 212,  40, 
-     57, 230, 160, 198, 151, 242, 
-    106, 110,   1,   0,   0,   0, 
+     68,  88,  66,  67, 181, 118, 
+    100,  53, 248, 120, 136,  92, 
+     59, 190,  18, 201, 139, 224, 
+     32, 141,   1,   0,   0,   0, 
     212,   7,   0,   0,   6,   0, 
       0,   0,  56,   0,   0,   0, 
     220,   1,   0,   0,  44,   4, 
       0,   0, 168,   4,   0,   0, 
      72,   7,   0,   0, 160,   7, 
       0,   0,  65, 111, 110,  57, 
     156,   1,   0,   0, 156,   1, 
       0,   0,   0,   2, 255, 255, 
@@ -1891,27 +1885,27 @@ const BYTE YCbCrShader[] =
      70,  14,  16,   0,   1,   0, 
       0,   0,   6, 128,  32,   0, 
       0,   0,   0,   0,   1,   0, 
       0,   0,  62,   0,   0,   1, 
      83,  84,  65,  84, 116,   0, 
       0,   0,  15,   0,   0,   0, 
       3,   0,   0,   0,   0,   0, 
       0,   0,   2,   0,   0,   0, 
-      6,   0,   0,   0,   0,   0, 
+     10,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       1,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   3,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
-      2,   0,   0,   0,   0,   0, 
+      1,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,  82,  68, 
      69,  70, 152,   2,   0,   0, 
       1,   0,   0,   0, 220,   0, 
@@ -2017,19 +2011,19 @@ const BYTE YCbCrShader[] =
      97, 100,   0, 118,  77,  97, 
     115, 107,  81, 117,  97, 100, 
       0,  77, 105,  99, 114, 111, 
     115, 111, 102, 116,  32,  40, 
      82,  41,  32,  72,  76,  83, 
      76,  32,  83, 104,  97, 100, 
     101, 114,  32,  67, 111, 109, 
     112, 105, 108, 101, 114,  32, 
-     57,  46,  51,  48,  46,  57, 
-     50,  48,  48,  46,  50,  48, 
-     53,  52,  54,   0,  73,  83, 
+     54,  46,  51,  46,  57,  54, 
+     48,  48,  46,  49,  54,  51, 
+     56,  52,   0, 171,  73,  83, 
      71,  78,  80,   0,   0,   0, 
       2,   0,   0,   0,   8,   0, 
       0,   0,  56,   0,   0,   0, 
       0,   0,   0,   0,   1,   0, 
       0,   0,   3,   0,   0,   0, 
       0,   0,   0,   0,  15,   0, 
       0,   0,  68,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
@@ -2046,20 +2040,19 @@ const BYTE YCbCrShader[] =
       0,   0,   0,   0,   0,   0, 
       3,   0,   0,   0,   0,   0, 
       0,   0,  15,   0,   0,   0, 
      83,  86,  95,  84,  97, 114, 
     103, 101, 116,   0, 171, 171
 };
 #if 0
 //
-// Generated by Microsoft (R) HLSL Shader Compiler 9.30.9200.20546
-//
-//
-///
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
 // Buffer Definitions: 
 //
 // cbuffer $Globals
 // {
 //
 //   float4x4 mLayerTransform;          // Offset:    0 Size:    64
 //   float4x4 mProjection;              // Offset:   64 Size:    64
 //   float4 vRenderTargetOffset;        // Offset:  128 Size:    16
@@ -2160,20 +2153,20 @@ mad r1.xyzw, cb0[6].xyzw, r0.zzzz, r1.xy
 mad o0.xyzw, cb0[7].xyzw, r0.wwww, r1.xyzw
 mad o1.xy, v0.xyxx, cb0[9].zwzz, cb0[9].xyxx
 ret 
 // Approximately 16 instruction slots used
 #endif
 
 const BYTE LayerQuadMaskVS[] =
 {
-     68,  88,  66,  67, 229,  18, 
-    238, 182, 176, 120, 118,  84, 
-     74, 135, 103, 188, 146,  51, 
-    229, 207,   1,   0,   0,   0, 
+     68,  88,  66,  67, 223, 251, 
+     10,  17,  13,  90,  47,  25, 
+    119, 198,  20, 157, 124, 193, 
+    251, 234,   1,   0,   0,   0, 
     120,   7,   0,   0,   6,   0, 
       0,   0,  56,   0,   0,   0, 
     224,   1,   0,   0,  76,   4, 
       0,   0, 200,   4,   0,   0, 
     212,   6,   0,   0,   8,   7, 
       0,   0,  65, 111, 110,  57, 
     160,   1,   0,   0, 160,   1, 
       0,   0,   0,   2, 254, 255, 
@@ -2347,27 +2340,27 @@ const BYTE LayerQuadMaskVS[] =
      32,   0,   0,   0,   0,   0, 
       9,   0,   0,   0,  70, 128, 
      32,   0,   0,   0,   0,   0, 
       9,   0,   0,   0,  62,   0, 
       0,   1,  83,  84,  65,  84, 
     116,   0,   0,   0,  16,   0, 
       0,   0,   2,   0,   0,   0, 
       0,   0,   0,   0,   4,   0, 
-      0,   0,   8,   0,   0,   0, 
+      0,   0,  14,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   1,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
-      0,   0,   2,   0,   0,   0, 
+      0,   0,   1,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
      82,  68,  69,  70,   4,   2, 
       0,   0,   1,   0,   0,   0, 
@@ -2448,20 +2441,20 @@ const BYTE LayerQuadMaskVS[] =
       0,   0,   3,   0,   1,   0, 
       1,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,  77, 105, 
      99, 114, 111, 115, 111, 102, 
     116,  32,  40,  82,  41,  32, 
      72,  76,  83,  76,  32,  83, 
     104,  97, 100, 101, 114,  32, 
      67, 111, 109, 112, 105, 108, 
-    101, 114,  32,  57,  46,  51, 
-     48,  46,  57,  50,  48,  48, 
-     46,  50,  48,  53,  52,  54, 
-      0, 171,  73,  83,  71,  78, 
+    101, 114,  32,  54,  46,  51, 
+     46,  57,  54,  48,  48,  46, 
+     49,  54,  51,  56,  52,   0, 
+    171, 171,  73,  83,  71,  78, 
      44,   0,   0,   0,   1,   0, 
       0,   0,   8,   0,   0,   0, 
      32,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       3,   0,   0,   0,   0,   0, 
       0,   0,   3,   3,   0,   0, 
      80,  79,  83,  73,  84,  73, 
      79,  78,   0, 171, 171, 171, 
@@ -2482,20 +2475,19 @@ const BYTE LayerQuadMaskVS[] =
      12,   3,   0,   0,  83,  86, 
      95,  80, 111, 115, 105, 116, 
     105, 111, 110,   0,  84,  69, 
      88,  67,  79,  79,  82,  68, 
       0, 171, 171, 171
 };
 #if 0
 //
-// Generated by Microsoft (R) HLSL Shader Compiler 9.30.9200.20546
-//
-//
-///
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
 // Buffer Definitions: 
 //
 // cbuffer $Globals
 // {
 //
 //   float4x4 mLayerTransform;          // Offset:    0 Size:    64
 //   float4x4 mProjection;              // Offset:   64 Size:    64
 //   float4 vRenderTargetOffset;        // Offset:  128 Size:    16
@@ -2600,20 +2592,20 @@ mad o1.xy, v0.xyxx, cb0[9].zwzz, cb0[9].
 mov r0.z, l(1.000000)
 mul o2.xyz, r0.wwww, r0.xyzx
 ret 
 // Approximately 17 instruction slots used
 #endif
 
 const BYTE LayerQuadMask3DVS[] =
 {
-     68,  88,  66,  67,  81, 198, 
-     45,  88, 207, 133,  27,  66, 
-      4, 235, 107, 238,  69,  93, 
-     43, 232,   1,   0,   0,   0, 
+     68,  88,  66,  67, 151, 141, 
+     11,  11, 111, 244,  17, 242, 
+    119, 116, 248,  53, 235, 192, 
+     38, 193,   1,   0,   0,   0, 
     204,   7,   0,   0,   6,   0, 
       0,   0,  56,   0,   0,   0, 
      24,   2,   0,   0, 160,   4, 
       0,   0,  28,   5,   0,   0, 
      40,   7,   0,   0,  92,   7, 
       0,   0,  65, 111, 110,  57, 
     216,   1,   0,   0, 216,   1, 
       0,   0,   0,   2, 254, 255, 
@@ -2801,27 +2793,27 @@ const BYTE LayerQuadMask3DVS[] =
      16,   0,   2,   0,   0,   0, 
     246,  15,  16,   0,   0,   0, 
       0,   0,  70,   2,  16,   0, 
       0,   0,   0,   0,  62,   0, 
       0,   1,  83,  84,  65,  84, 
     116,   0,   0,   0,  17,   0, 
       0,   0,   3,   0,   0,   0, 
       0,   0,   0,   0,   4,   0, 
-      0,   0,   9,   0,   0,   0, 
+      0,   0,  15,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   1,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
-      0,   0,   3,   0,   0,   0, 
+      0,   0,   1,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
      82,  68,  69,  70,   4,   2, 
       0,   0,   1,   0,   0,   0, 
@@ -2902,20 +2894,20 @@ const BYTE LayerQuadMask3DVS[] =
       0,   0,   3,   0,   1,   0, 
       1,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,  77, 105, 
      99, 114, 111, 115, 111, 102, 
     116,  32,  40,  82,  41,  32, 
      72,  76,  83,  76,  32,  83, 
     104,  97, 100, 101, 114,  32, 
      67, 111, 109, 112, 105, 108, 
-    101, 114,  32,  57,  46,  51, 
-     48,  46,  57,  50,  48,  48, 
-     46,  50,  48,  53,  52,  54, 
-      0, 171,  73,  83,  71,  78, 
+    101, 114,  32,  54,  46,  51, 
+     46,  57,  54,  48,  48,  46, 
+     49,  54,  51,  56,  52,   0, 
+    171, 171,  73,  83,  71,  78, 
      44,   0,   0,   0,   1,   0, 
       0,   0,   8,   0,   0,   0, 
      32,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       3,   0,   0,   0,   0,   0, 
       0,   0,   3,   3,   0,   0, 
      80,  79,  83,  73,  84,  73, 
      79,  78,   0, 171, 171, 171, 
@@ -2936,20 +2928,19 @@ const BYTE LayerQuadMask3DVS[] =
       7,   8,   0,   0,  83,  86, 
      95,  80, 111, 115, 105, 116, 
     105, 111, 110,   0,  84,  69, 
      88,  67,  79,  79,  82,  68, 
       0, 171, 171, 171
 };
 #if 0
 //
-// Generated by Microsoft (R) HLSL Shader Compiler 9.30.9200.20546
-//
-//
-///
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
 // Buffer Definitions: 
 //
 // cbuffer $Globals
 // {
 //
 //   float4 fLayerColor;                // Offset:    0 Size:    16
 //   float fLayerOpacity;               // Offset:   16 Size:     4 [unused]
 //   float4x4 mLayerTransform;          // Offset:   32 Size:    64 [unused]
@@ -3023,20 +3014,20 @@ dcl_temps 1
 sample r0.xyzw, v1.zwzz, t3.xyzw, s0
 mul o0.xyzw, r0.wwww, cb0[0].xyzw
 ret 
 // Approximately 3 instruction slots used
 #endif
 
 const BYTE SolidColorShaderMask[] =
 {
-     68,  88,  66,  67, 110, 173, 
-    179, 170, 121,  56,  16,  38, 
-    131, 202, 191, 200, 149, 158, 
-    191, 136,   1,   0,   0,   0, 
+     68,  88,  66,  67, 236, 109, 
+     19, 151,  23, 187, 157, 205, 
+    112, 188,  91, 187, 108, 106, 
+    138,  14,   1,   0,   0,   0, 
     232,   4,   0,   0,   6,   0, 
       0,   0,  56,   0,   0,   0, 
     204,   0,   0,   0, 112,   1, 
       0,   0, 236,   1,   0,   0, 
      68,   4,   0,   0, 180,   4, 
       0,   0,  65, 111, 110,  57, 
     140,   0,   0,   0, 140,   0, 
       0,   0,   0,   2, 255, 255, 
@@ -3098,17 +3089,17 @@ const BYTE SolidColorShaderMask[] =
       0,   0,   1,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       1,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
-      0,   0,   1,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
      82,  68,  69,  70,  80,   2, 
       0,   0,   1,   0,   0,   0, 
@@ -3202,19 +3193,19 @@ const BYTE SolidColorShaderMask[] =
      81, 117,  97, 100,   0, 118, 
      77,  97, 115, 107,  81, 117, 
      97, 100,   0,  77, 105,  99, 
     114, 111, 115, 111, 102, 116, 
      32,  40,  82,  41,  32,  72, 
      76,  83,  76,  32,  83, 104, 
      97, 100, 101, 114,  32,  67, 
     111, 109, 112, 105, 108, 101, 
-    114,  32,  57,  46,  51,  48, 
-     46,  57,  50,  48,  48,  46, 
-     50,  48,  53,  52,  54,   0, 
+    114,  32,  54,  46,  51,  46, 
+     57,  54,  48,  48,  46,  49, 
+     54,  51,  56,  52,   0, 171, 
      73,  83,  71,  78, 104,   0, 
       0,   0,   3,   0,   0,   0, 
       8,   0,   0,   0,  80,   0, 
       0,   0,   0,   0,   0,   0, 
       1,   0,   0,   0,   3,   0, 
       0,   0,   0,   0,   0,   0, 
      15,   0,   0,   0,  92,   0, 
       0,   0,   0,   0,   0,   0, 
@@ -3236,20 +3227,19 @@ const BYTE SolidColorShaderMask[] =
       0,   0,   3,   0,   0,   0, 
       0,   0,   0,   0,  15,   0, 
       0,   0,  83,  86,  95,  84, 
      97, 114, 103, 101, 116,   0, 
     171, 171
 };
 #if 0
 //
-// Generated by Microsoft (R) HLSL Shader Compiler 9.30.9200.20546
-//
-//
-///
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
 // Buffer Definitions: 
 //
 // cbuffer $Globals
 // {
 //
 //   float4 fLayerColor;                // Offset:    0 Size:    16 [unused]
 //   float fLayerOpacity;               // Offset:   16 Size:     4
 //   float4x4 mLayerTransform;          // Offset:   32 Size:    64 [unused]
@@ -3334,20 +3324,20 @@ sample r1.xyzw, v1.zwzz, t3.xyzw, s0
 mov r0.w, cb0[1].x
 mul o0.xyzw, r0.xyzw, r1.wwww
 ret 
 // Approximately 6 instruction slots used
 #endif
 
 const BYTE RGBShaderMask[] =
 {
-     68,  88,  66,  67,  90, 156, 
-    108, 215,   2, 184,  95, 225, 
-    139, 102,  23,  57, 234, 197, 
-     48,  52,   1,   0,   0,   0, 
+     68,  88,  66,  67,  30,  30, 
+     87,  58, 114, 156, 251, 151, 
+     29,  94,  34, 100, 228, 250, 
+     37, 251,   1,   0,   0,   0, 
     192,   5,   0,   0,   6,   0, 
       0,   0,  56,   0,   0,   0, 
       8,   1,   0,   0,  32,   2, 
       0,   0, 156,   2,   0,   0, 
      28,   5,   0,   0, 140,   5, 
       0,   0,  65, 111, 110,  57, 
     200,   0,   0,   0, 200,   0, 
       0,   0,   0,   2, 255, 255, 
@@ -3438,355 +3428,16 @@ const BYTE RGBShaderMask[] =
       0,   0,   0,   0,   1,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   2,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   2,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,  82,  68,  69,  70, 
-    120,   2,   0,   0,   1,   0, 
-      0,   0, 188,   0,   0,   0, 
-      4,   0,   0,   0,  28,   0, 
-      0,   0,   0,   4, 255, 255, 
-      0,   1,   0,   0,  69,   2, 
-      0,   0, 156,   0,   0,   0, 
-      3,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   1,   0,   0,   0, 
-      1,   0,   0,   0, 165,   0, 
-      0,   0,   2,   0,   0,   0, 
-      5,   0,   0,   0,   4,   0, 
-      0,   0, 255, 255, 255, 255, 
-      0,   0,   0,   0,   1,   0, 
-      0,   0,  12,   0,   0,   0, 
-    170,   0,   0,   0,   2,   0, 
-      0,   0,   5,   0,   0,   0, 
-      4,   0,   0,   0, 255, 255, 
-    255, 255,   3,   0,   0,   0, 
-      1,   0,   0,   0,  13,   0, 
-      0,   0, 176,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   1,   0,   0,   0, 
-      0,   0,   0,   0, 115,  83, 
-     97, 109, 112, 108, 101, 114, 
-      0, 116,  82,  71,  66,   0, 
-    116,  77,  97, 115, 107,   0, 
-     36,  71, 108, 111,  98,  97, 
-    108, 115,   0, 171, 171, 171, 
-    176,   0,   0,   0,   8,   0, 
-      0,   0, 212,   0,   0,   0, 
-    224,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-    148,   1,   0,   0,   0,   0, 
-      0,   0,  16,   0,   0,   0, 
-      0,   0,   0,   0, 160,   1, 
-      0,   0,   0,   0,   0,   0, 
-    176,   1,   0,   0,  16,   0, 
-      0,   0,   4,   0,   0,   0, 
-      2,   0,   0,   0, 192,   1, 
-      0,   0,   0,   0,   0,   0, 
-    208,   1,   0,   0,  32,   0, 
-      0,   0,  64,   0,   0,   0, 
-      0,   0,   0,   0, 224,   1, 
-      0,   0,   0,   0,   0,   0, 
-    240,   1,   0,   0,  96,   0, 
-      0,   0,  64,   0,   0,   0, 
-      0,   0,   0,   0, 224,   1, 
-      0,   0,   0,   0,   0,   0, 
-    252,   1,   0,   0, 160,   0, 
-      0,   0,  16,   0,   0,   0, 
-      0,   0,   0,   0, 160,   1, 
-      0,   0,   0,   0,   0,   0, 
-     16,   2,   0,   0, 176,   0, 
-      0,   0,  16,   0,   0,   0, 
-      0,   0,   0,   0,  32,   2, 
-      0,   0,   0,   0,   0,   0, 
-     48,   2,   0,   0, 192,   0, 
-      0,   0,  16,   0,   0,   0, 
-      0,   0,   0,   0,  32,   2, 
-      0,   0,   0,   0,   0,   0, 
-     59,   2,   0,   0, 208,   0, 
-      0,   0,  16,   0,   0,   0, 
-      0,   0,   0,   0,  32,   2, 
-      0,   0,   0,   0,   0,   0, 
-    102,  76,  97, 121, 101, 114, 
-     67, 111, 108, 111, 114,   0, 
-      1,   0,   3,   0,   1,   0, 
-      4,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0, 102,  76, 
-     97, 121, 101, 114,  79, 112, 
-     97,  99, 105, 116, 121,   0, 
-    171, 171,   0,   0,   3,   0, 
-      1,   0,   1,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-    109,  76,  97, 121, 101, 114, 
-     84, 114,  97, 110, 115, 102, 
-    111, 114, 109,   0,   3,   0, 
-      3,   0,   4,   0,   4,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0, 109,  80, 114, 111, 
-    106, 101,  99, 116, 105, 111, 
-    110,   0, 118,  82, 101, 110, 
-    100, 101, 114,  84,  97, 114, 
-    103, 101, 116,  79, 102, 102, 
-    115, 101, 116,   0, 118,  84, 
-    101, 120, 116, 117, 114, 101, 
-     67, 111, 111, 114, 100, 115, 
-      0, 171,   1,   0,   3,   0, 
-      1,   0,   4,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-    118,  76,  97, 121, 101, 114, 
-     81, 117,  97, 100,   0, 118, 
-     77,  97, 115, 107,  81, 117, 
-     97, 100,   0,  77, 105,  99, 
-    114, 111, 115, 111, 102, 116, 
-     32,  40,  82,  41,  32,  72, 
-     76,  83,  76,  32,  83, 104, 
-     97, 100, 101, 114,  32,  67, 
-    111, 109, 112, 105, 108, 101, 
-    114,  32,  57,  46,  51,  48, 
-     46,  57,  50,  48,  48,  46, 
-     50,  48,  53,  52,  54,   0, 
-     73,  83,  71,  78, 104,   0, 
-      0,   0,   3,   0,   0,   0, 
-      8,   0,   0,   0,  80,   0, 
-      0,   0,   0,   0,   0,   0, 
-      1,   0,   0,   0,   3,   0, 
-      0,   0,   0,   0,   0,   0, 
-     15,   0,   0,   0,  92,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   3,   0, 
-      0,   0,   1,   0,   0,   0, 
-      3,   3,   0,   0,  92,   0, 
-      0,   0,   1,   0,   0,   0, 
-      0,   0,   0,   0,   3,   0, 
-      0,   0,   1,   0,   0,   0, 
-     12,  12,   0,   0,  83,  86, 
-     95,  80, 111, 115, 105, 116, 
-    105, 111, 110,   0,  84,  69, 
-     88,  67,  79,  79,  82,  68, 
-      0, 171, 171, 171,  79,  83, 
-     71,  78,  44,   0,   0,   0, 
-      1,   0,   0,   0,   8,   0, 
-      0,   0,  32,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   3,   0,   0,   0, 
-      0,   0,   0,   0,  15,   0, 
-      0,   0,  83,  86,  95,  84, 
-     97, 114, 103, 101, 116,   0, 
-    171, 171
-};
-#if 0
-//
-// Generated by Microsoft (R) HLSL Shader Compiler 9.30.9200.20546
-//
-//
-///
-// Buffer Definitions: 
-//
-// cbuffer $Globals
-// {
-//
-//   float4 fLayerColor;                // Offset:    0 Size:    16 [unused]
-//   float fLayerOpacity;               // Offset:   16 Size:     4
-//   float4x4 mLayerTransform;          // Offset:   32 Size:    64 [unused]
-//   float4x4 mProjection;              // Offset:   96 Size:    64 [unused]
-//   float4 vRenderTargetOffset;        // Offset:  160 Size:    16 [unused]
-//   float4 vTextureCoords;             // Offset:  176 Size:    16 [unused]
-//   float4 vLayerQuad;                 // Offset:  192 Size:    16 [unused]
-//   float4 vMaskQuad;                  // Offset:  208 Size:    16 [unused]
-//
-// }
-//
-//
-// Resource Bindings:
-//
-// Name                                 Type  Format         Dim Slot Elements
-// ------------------------------ ---------- ------- ----------- ---- --------
-// sSampler                          sampler      NA          NA    0        1
-// tRGB                              texture  float4          2d    0        1
-// tMask                             texture  float4          2d    3        1
-// $Globals                          cbuffer      NA          NA    0        1
-//
-//
-//
-// Input signature:
-//
-// Name                 Index   Mask Register SysValue  Format   Used
-// -------------------- ----- ------ -------- -------- ------- ------
-// SV_Position              0   xyzw        0      POS   float       
-// TEXCOORD                 0   xy          1     NONE   float   xy  
-// TEXCOORD                 1     zw        1     NONE   float     zw
-//
-//
-// Output signature:
-//
-// Name                 Index   Mask Register SysValue  Format   Used
-// -------------------- ----- ------ -------- -------- ------- ------
-// SV_Target                0   xyzw        0   TARGET   float   xyzw
-//
-//
-// Constant buffer to DX9 shader constant mappings:
-//
-// Target Reg Buffer  Start Reg # of Regs        Data Conversion
-// ---------- ------- --------- --------- ----------------------
-// c0         cb0             1         1  ( FLT, FLT, FLT, FLT)
-//
-//
-// Sampler/Resource to DX9 shader sampler mappings:
-//
-// Target Sampler Source Sampler  Source Resource
-// -------------- --------------- ----------------
-// s0             s0              t3               
-// s1             s0              t0               
-//
-//
-// Level9 shader bytecode:
-//
-    ps_2_x
-    dcl t0
-    dcl_2d s0
-    dcl_2d s1
-    mov r0.xy, t0.wzzw
-    texld r1, t0, s1
-    texld r0, r0, s0
-    mul r1, r1, c0.x
-    mul r0, r0.w, r1
-    mov oC0, r0
-
-// approximately 6 instruction slots used (2 texture, 4 arithmetic)
-ps_4_0
-dcl_constantbuffer cb0[2], immediateIndexed
-dcl_sampler s0, mode_default
-dcl_resource_texture2d (float,float,float,float) t0
-dcl_resource_texture2d (float,float,float,float) t3
-dcl_input_ps linear v1.xy
-dcl_input_ps linear v1.zw
-dcl_output o0.xyzw
-dcl_temps 2
-sample r0.xyzw, v1.xyxx, t0.xyzw, s0
-mul r0.xyzw, r0.xyzw, cb0[1].xxxx
-sample r1.xyzw, v1.zwzz, t3.xyzw, s0
-mul o0.xyzw, r0.xyzw, r1.wwww
-ret 
-// Approximately 5 instruction slots used
-#endif
-
-const BYTE RGBAShaderMask[] =
-{
-     68,  88,  66,  67, 106,  15, 
-     51,  47, 230,  18,  55,  40, 
-     97,  21, 143,  67,  32,  99, 
-    176,  32,   1,   0,   0,   0, 
-    156,   5,   0,   0,   6,   0, 
-      0,   0,  56,   0,   0,   0, 
-    252,   0,   0,   0, 252,   1, 
-      0,   0, 120,   2,   0,   0, 
-    248,   4,   0,   0, 104,   5, 
-      0,   0,  65, 111, 110,  57, 
-    188,   0,   0,   0, 188,   0, 
-      0,   0,   0,   2, 255, 255, 
-    132,   0,   0,   0,  56,   0, 
-      0,   0,   1,   0,  44,   0, 
-      0,   0,  56,   0,   0,   0, 
-     56,   0,   2,   0,  36,   0, 
-      0,   0,  56,   0,   3,   0, 
-      0,   0,   0,   0,   1,   0, 
-      0,   0,   1,   0,   1,   0, 
-      0,   0,   0,   0,   0,   0, 
-      1,   2, 255, 255,  31,   0, 
-      0,   2,   0,   0,   0, 128, 
-      0,   0,  15, 176,  31,   0, 
-      0,   2,   0,   0,   0, 144, 
-      0,   8,  15, 160,  31,   0, 
-      0,   2,   0,   0,   0, 144, 
-      1,   8,  15, 160,   1,   0, 
-      0,   2,   0,   0,   3, 128, 
-      0,   0, 235, 176,  66,   0, 
-      0,   3,   1,   0,  15, 128, 
-      0,   0, 228, 176,   1,   8, 
-    228, 160,  66,   0,   0,   3, 
-      0,   0,  15, 128,   0,   0, 
-    228, 128,   0,   8, 228, 160, 
-      5,   0,   0,   3,   1,   0, 
-     15, 128,   1,   0, 228, 128, 
-      0,   0,   0, 160,   5,   0, 
-      0,   3,   0,   0,  15, 128, 
-      0,   0, 255, 128,   1,   0, 
-    228, 128,   1,   0,   0,   2, 
-      0,   8,  15, 128,   0,   0, 
-    228, 128, 255, 255,   0,   0, 
-     83,  72,  68,  82, 248,   0, 
-      0,   0,  64,   0,   0,   0, 
-     62,   0,   0,   0,  89,   0, 
-      0,   4,  70, 142,  32,   0, 
-      0,   0,   0,   0,   2,   0, 
-      0,   0,  90,   0,   0,   3, 
-      0,  96,  16,   0,   0,   0, 
-      0,   0,  88,  24,   0,   4, 
-      0, 112,  16,   0,   0,   0, 
-      0,   0,  85,  85,   0,   0, 
-     88,  24,   0,   4,   0, 112, 
-     16,   0,   3,   0,   0,   0, 
-     85,  85,   0,   0,  98,  16, 
-      0,   3,  50,  16,  16,   0, 
-      1,   0,   0,   0,  98,  16, 
-      0,   3, 194,  16,  16,   0, 
-      1,   0,   0,   0, 101,   0, 
-      0,   3, 242,  32,  16,   0, 
-      0,   0,   0,   0, 104,   0, 
-      0,   2,   2,   0,   0,   0, 
-     69,   0,   0,   9, 242,   0, 
-     16,   0,   0,   0,   0,   0, 
-     70,  16,  16,   0,   1,   0, 
-      0,   0,  70, 126,  16,   0, 
-      0,   0,   0,   0,   0,  96, 
-     16,   0,   0,   0,   0,   0, 
-     56,   0,   0,   8, 242,   0, 
-     16,   0,   0,   0,   0,   0, 
-     70,  14,  16,   0,   0,   0, 
-      0,   0,   6, 128,  32,   0, 
-      0,   0,   0,   0,   1,   0, 
-      0,   0,  69,   0,   0,   9, 
-    242,   0,  16,   0,   1,   0, 
-      0,   0, 230,  26,  16,   0, 
-      1,   0,   0,   0,  70, 126, 
-     16,   0,   3,   0,   0,   0, 
-      0,  96,  16,   0,   0,   0, 
-      0,   0,  56,   0,   0,   7, 
-    242,  32,  16,   0,   0,   0, 
-      0,   0,  70,  14,  16,   0, 
-      0,   0,   0,   0, 246,  15, 
-     16,   0,   1,   0,   0,   0, 
-     62,   0,   0,   1,  83,  84, 
-     65,  84, 116,   0,   0,   0, 
-      5,   0,   0,   0,   2,   0, 
-      0,   0,   0,   0,   0,   0, 
-      3,   0,   0,   0,   2,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   1,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   2,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   1,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,  82,  68,  69,  70, 
@@ -3888,19 +3539,19 @@ const BYTE RGBAShaderMask[] =
      81, 117,  97, 100,   0, 118, 
      77,  97, 115, 107,  81, 117, 
      97, 100,   0,  77, 105,  99, 
     114, 111, 115, 111, 102, 116, 
      32,  40,  82,  41,  32,  72, 
      76,  83,  76,  32,  83, 104, 
      97, 100, 101, 114,  32,  67, 
     111, 109, 112, 105, 108, 101, 
-    114,  32,  57,  46,  51,  48, 
-     46,  57,  50,  48,  48,  46, 
-     50,  48,  53,  52,  54,   0, 
+    114,  32,  54,  46,  51,  46, 
+     57,  54,  48,  48,  46,  49, 
+     54,  51,  56,  52,   0, 171, 
      73,  83,  71,  78, 104,   0, 
       0,   0,   3,   0,   0,   0, 
       8,   0,   0,   0,  80,   0, 
       0,   0,   0,   0,   0,   0, 
       1,   0,   0,   0,   3,   0, 
       0,   0,   0,   0,   0,   0, 
      15,   0,   0,   0,  92,   0, 
       0,   0,   0,   0,   0,   0, 
@@ -3922,20 +3573,357 @@ const BYTE RGBAShaderMask[] =
       0,   0,   3,   0,   0,   0, 
       0,   0,   0,   0,  15,   0, 
       0,   0,  83,  86,  95,  84, 
      97, 114, 103, 101, 116,   0, 
     171, 171
 };
 #if 0
 //
-// Generated by Microsoft (R) HLSL Shader Compiler 9.30.9200.20546
-//
-//
-///
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Buffer Definitions: 
+//
+// cbuffer $Globals
+// {
+//
+//   float4 fLayerColor;                // Offset:    0 Size:    16 [unused]
+//   float fLayerOpacity;               // Offset:   16 Size:     4
+//   float4x4 mLayerTransform;          // Offset:   32 Size:    64 [unused]
+//   float4x4 mProjection;              // Offset:   96 Size:    64 [unused]
+//   float4 vRenderTargetOffset;        // Offset:  160 Size:    16 [unused]
+//   float4 vTextureCoords;             // Offset:  176 Size:    16 [unused]
+//   float4 vLayerQuad;                 // Offset:  192 Size:    16 [unused]
+//   float4 vMaskQuad;                  // Offset:  208 Size:    16 [unused]
+//
+// }
+//
+//
+// Resource Bindings:
+//
+// Name                                 Type  Format         Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// sSampler                          sampler      NA          NA    0        1
+// tRGB                              texture  float4          2d    0        1
+// tMask                             texture  float4          2d    3        1
+// $Globals                          cbuffer      NA          NA    0        1
+//
+//
+//
+// Input signature:
+//
+// Name                 Index   Mask Register SysValue  Format   Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_Position              0   xyzw        0      POS   float       
+// TEXCOORD                 0   xy          1     NONE   float   xy  
+// TEXCOORD                 1     zw        1     NONE   float     zw
+//
+//
+// Output signature:
+//
+// Name                 Index   Mask Register SysValue  Format   Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_Target                0   xyzw        0   TARGET   float   xyzw
+//
+//
+// Constant buffer to DX9 shader constant mappings:
+//
+// Target Reg Buffer  Start Reg # of Regs        Data Conversion
+// ---------- ------- --------- --------- ----------------------
+// c0         cb0             1         1  ( FLT, FLT, FLT, FLT)
+//
+//
+// Sampler/Resource to DX9 shader sampler mappings:
+//
+// Target Sampler Source Sampler  Source Resource
+// -------------- --------------- ----------------
+// s0             s0              t3               
+// s1             s0              t0               
+//
+//
+// Level9 shader bytecode:
+//
+    ps_2_x
+    dcl t0
+    dcl_2d s0
+    dcl_2d s1
+    mov r0.xy, t0.wzzw
+    texld r1, t0, s1
+    texld r0, r0, s0
+    mul r1, r1, c0.x
+    mul r0, r0.w, r1
+    mov oC0, r0
+
+// approximately 6 instruction slots used (2 texture, 4 arithmetic)
+ps_4_0
+dcl_constantbuffer cb0[2], immediateIndexed
+dcl_sampler s0, mode_default
+dcl_resource_texture2d (float,float,float,float) t0
+dcl_resource_texture2d (float,float,float,float) t3
+dcl_input_ps linear v1.xy
+dcl_input_ps linear v1.zw
+dcl_output o0.xyzw
+dcl_temps 2
+sample r0.xyzw, v1.xyxx, t0.xyzw, s0
+mul r0.xyzw, r0.xyzw, cb0[1].xxxx
+sample r1.xyzw, v1.zwzz, t3.xyzw, s0
+mul o0.xyzw, r0.xyzw, r1.wwww
+ret 
+// Approximately 5 instruction slots used
+#endif
+
+const BYTE RGBAShaderMask[] =
+{
+     68,  88,  66,  67, 188,  13, 
+    191, 168, 231, 201,  42, 209, 
+     88, 243,  29,  35, 226,  31, 
+    145,  20,   1,   0,   0,   0, 
+    156,   5,   0,   0,   6,   0, 
+      0,   0,  56,   0,   0,   0, 
+    252,   0,   0,   0, 252,   1, 
+      0,   0, 120,   2,   0,   0, 
+    248,   4,   0,   0, 104,   5, 
+      0,   0,  65, 111, 110,  57, 
+    188,   0,   0,   0, 188,   0, 
+      0,   0,   0,   2, 255, 255, 
+    132,   0,   0,   0,  56,   0, 
+      0,   0,   1,   0,  44,   0, 
+      0,   0,  56,   0,   0,   0, 
+     56,   0,   2,   0,  36,   0, 
+      0,   0,  56,   0,   3,   0, 
+      0,   0,   0,   0,   1,   0, 
+      0,   0,   1,   0,   1,   0, 
+      0,   0,   0,   0,   0,   0, 
+      1,   2, 255, 255,  31,   0, 
+      0,   2,   0,   0,   0, 128, 
+      0,   0,  15, 176,  31,   0, 
+      0,   2,   0,   0,   0, 144, 
+      0,   8,  15, 160,  31,   0, 
+      0,   2,   0,   0,   0, 144, 
+      1,   8,  15, 160,   1,   0, 
+      0,   2,   0,   0,   3, 128, 
+      0,   0, 235, 176,  66,   0, 
+      0,   3,   1,   0,  15, 128, 
+      0,   0, 228, 176,   1,   8, 
+    228, 160,  66,   0,   0,   3, 
+      0,   0,  15, 128,   0,   0, 
+    228, 128,   0,   8, 228, 160, 
+      5,   0,   0,   3,   1,   0, 
+     15, 128,   1,   0, 228, 128, 
+      0,   0,   0, 160,   5,   0, 
+      0,   3,   0,   0,  15, 128, 
+      0,   0, 255, 128,   1,   0, 
+    228, 128,   1,   0,   0,   2, 
+      0,   8,  15, 128,   0,   0, 
+    228, 128, 255, 255,   0,   0, 
+     83,  72,  68,  82, 248,   0, 
+      0,   0,  64,   0,   0,   0, 
+     62,   0,   0,   0,  89,   0, 
+      0,   4,  70, 142,  32,   0, 
+      0,   0,   0,   0,   2,   0, 
+      0,   0,  90,   0,   0,   3, 
+      0,  96,  16,   0,   0,   0, 
+      0,   0,  88,  24,   0,   4, 
+      0, 112,  16,   0,   0,   0, 
+      0,   0,  85,  85,   0,   0, 
+     88,  24,   0,   4,   0, 112, 
+     16,   0,   3,   0,   0,   0, 
+     85,  85,   0,   0,  98,  16, 
+      0,   3,  50,  16,  16,   0, 
+      1,   0,   0,   0,  98,  16, 
+      0,   3, 194,  16,  16,   0, 
+      1,   0,   0,   0, 101,   0, 
+      0,   3, 242,  32,  16,   0, 
+      0,   0,   0,   0, 104,   0, 
+      0,   2,   2,   0,   0,   0, 
+     69,   0,   0,   9, 242,   0, 
+     16,   0,   0,   0,   0,   0, 
+     70,  16,  16,   0,   1,   0, 
+      0,   0,  70, 126,  16,   0, 
+      0,   0,   0,   0,   0,  96, 
+     16,   0,   0,   0,   0,   0, 
+     56,   0,   0,   8, 242,   0, 
+     16,   0,   0,   0,   0,   0, 
+     70,  14,  16,   0,   0,   0, 
+      0,   0,   6, 128,  32,   0, 
+      0,   0,   0,   0,   1,   0, 
+      0,   0,  69,   0,   0,   9, 
+    242,   0,  16,   0,   1,   0, 
+      0,   0, 230,  26,  16,   0, 
+      1,   0,   0,   0,  70, 126, 
+     16,   0,   3,   0,   0,   0, 
+      0,  96,  16,   0,   0,   0, 
+      0,   0,  56,   0,   0,   7, 
+    242,  32,  16,   0,   0,   0, 
+      0,   0,  70,  14,  16,   0, 
+      0,   0,   0,   0, 246,  15, 
+     16,   0,   1,   0,   0,   0, 
+     62,   0,   0,   1,  83,  84, 
+     65,  84, 116,   0,   0,   0, 
+      5,   0,   0,   0,   2,   0, 
+      0,   0,   0,   0,   0,   0, 
+      3,   0,   0,   0,   2,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   1,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   2,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,  82,  68,  69,  70, 
+    120,   2,   0,   0,   1,   0, 
+      0,   0, 188,   0,   0,   0, 
+      4,   0,   0,   0,  28,   0, 
+      0,   0,   0,   4, 255, 255, 
+      0,   1,   0,   0,  69,   2, 
+      0,   0, 156,   0,   0,   0, 
+      3,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   1,   0,   0,   0, 
+      1,   0,   0,   0, 165,   0, 
+      0,   0,   2,   0,   0,   0, 
+      5,   0,   0,   0,   4,   0, 
+      0,   0, 255, 255, 255, 255, 
+      0,   0,   0,   0,   1,   0, 
+      0,   0,  12,   0,   0,   0, 
+    170,   0,   0,   0,   2,   0, 
+      0,   0,   5,   0,   0,   0, 
+      4,   0,   0,   0, 255, 255, 
+    255, 255,   3,   0,   0,   0, 
+      1,   0,   0,   0,  13,   0, 
+      0,   0, 176,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   1,   0,   0,   0, 
+      0,   0,   0,   0, 115,  83, 
+     97, 109, 112, 108, 101, 114, 
+      0, 116,  82,  71,  66,   0, 
+    116,  77,  97, 115, 107,   0, 
+     36,  71, 108, 111,  98,  97, 
+    108, 115,   0, 171, 171, 171, 
+    176,   0,   0,   0,   8,   0, 
+      0,   0, 212,   0,   0,   0, 
+    224,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+    148,   1,   0,   0,   0,   0, 
+      0,   0,  16,   0,   0,   0, 
+      0,   0,   0,   0, 160,   1, 
+      0,   0,   0,   0,   0,   0, 
+    176,   1,   0,   0,  16,   0, 
+      0,   0,   4,   0,   0,   0, 
+      2,   0,   0,   0, 192,   1, 
+      0,   0,   0,   0,   0,   0, 
+    208,   1,   0,   0,  32,   0, 
+      0,   0,  64,   0,   0,   0, 
+      0,   0,   0,   0, 224,   1, 
+      0,   0,   0,   0,   0,   0, 
+    240,   1,   0,   0,  96,   0, 
+      0,   0,  64,   0,   0,   0, 
+      0,   0,   0,   0, 224,   1, 
+      0,   0,   0,   0,   0,   0, 
+    252,   1,   0,   0, 160,   0, 
+      0,   0,  16,   0,   0,   0, 
+      0,   0,   0,   0, 160,   1, 
+      0,   0,   0,   0,   0,   0, 
+     16,   2,   0,   0, 176,   0, 
+      0,   0,  16,   0,   0,   0, 
+      0,   0,   0,   0,  32,   2, 
+      0,   0,   0,   0,   0,   0, 
+     48,   2,   0,   0, 192,   0, 
+      0,   0,  16,   0,   0,   0, 
+      0,   0,   0,   0,  32,   2, 
+      0,   0,   0,   0,   0,   0, 
+     59,   2,   0,   0, 208,   0, 
+      0,   0,  16,   0,   0,   0, 
+      0,   0,   0,   0,  32,   2, 
+      0,   0,   0,   0,   0,   0, 
+    102,  76,  97, 121, 101, 114, 
+     67, 111, 108, 111, 114,   0, 
+      1,   0,   3,   0,   1,   0, 
+      4,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0, 102,  76, 
+     97, 121, 101, 114,  79, 112, 
+     97,  99, 105, 116, 121,   0, 
+    171, 171,   0,   0,   3,   0, 
+      1,   0,   1,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+    109,  76,  97, 121, 101, 114, 
+     84, 114,  97, 110, 115, 102, 
+    111, 114, 109,   0,   3,   0, 
+      3,   0,   4,   0,   4,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0, 109,  80, 114, 111, 
+    106, 101,  99, 116, 105, 111, 
+    110,   0, 118,  82, 101, 110, 
+    100, 101, 114,  84,  97, 114, 
+    103, 101, 116,  79, 102, 102, 
+    115, 101, 116,   0, 118,  84, 
+    101, 120, 116, 117, 114, 101, 
+     67, 111, 111, 114, 100, 115, 
+      0, 171,   1,   0,   3,   0, 
+      1,   0,   4,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+    118,  76,  97, 121, 101, 114, 
+     81, 117,  97, 100,   0, 118, 
+     77,  97, 115, 107,  81, 117, 
+     97, 100,   0,  77, 105,  99, 
+    114, 111, 115, 111, 102, 116, 
+     32,  40,  82,  41,  32,  72, 
+     76,  83,  76,  32,  83, 104, 
+     97, 100, 101, 114,  32,  67, 
+    111, 109, 112, 105, 108, 101, 
+    114,  32,  54,  46,  51,  46, 
+     57,  54,  48,  48,  46,  49, 
+     54,  51,  56,  52,   0, 171, 
+     73,  83,  71,  78, 104,   0, 
+      0,   0,   3,   0,   0,   0, 
+      8,   0,   0,   0,  80,   0, 
+      0,   0,   0,   0,   0,   0, 
+      1,   0,   0,   0,   3,   0, 
+      0,   0,   0,   0,   0,   0, 
+     15,   0,   0,   0,  92,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   3,   0, 
+      0,   0,   1,   0,   0,   0, 
+      3,   3,   0,   0,  92,   0, 
+      0,   0,   1,   0,   0,   0, 
+      0,   0,   0,   0,   3,   0, 
+      0,   0,   1,   0,   0,   0, 
+     12,  12,   0,   0,  83,  86, 
+     95,  80, 111, 115, 105, 116, 
+    105, 111, 110,   0,  84,  69, 
+     88,  67,  79,  79,  82,  68, 
+      0, 171, 171, 171,  79,  83, 
+     71,  78,  44,   0,   0,   0, 
+      1,   0,   0,   0,   8,   0, 
+      0,   0,  32,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   3,   0,   0,   0, 
+      0,   0,   0,   0,  15,   0, 
+      0,   0,  83,  86,  95,  84, 
+     97, 114, 103, 101, 116,   0, 
+    171, 171
+};
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
 // Buffer Definitions: 
 //
 // cbuffer $Globals
 // {
 //
 //   float4 fLayerColor;                // Offset:    0 Size:    16 [unused]
 //   float fLayerOpacity;               // Offset:   16 Size:     4
 //   float4x4 mLayerTransform;          // Offset:   32 Size:    64 [unused]
@@ -4023,20 +4011,20 @@ sample r1.xyzw, v1.xyxx, t0.xyzw, s0
 mul r1.xyzw, r1.xyzw, cb0[1].xxxx
 mul o0.xyzw, r0.wwww, r1.xyzw
 ret 
 // Approximately 6 instruction slots used
 #endif
 
 const BYTE RGBAShaderMask3D[] =
 {
-     68,  88,  66,  67, 176, 186, 
-     72,  64, 199, 228, 205, 219, 
-     97, 152, 199, 132, 157, 124, 
-    226, 212,   1,   0,   0,   0, 
+     68,  88,  66,  67, 113, 141, 
+     78,  23, 128, 223, 235,  10, 
+      0,  97,  49, 111,  47,  53, 
+    229,  55,   1,   0,   0,   0, 
      24,   6,   0,   0,   6,   0, 
       0,   0,  56,   0,   0,   0, 
      24,   1,   0,   0,  64,   2, 
       0,   0, 188,   2,   0,   0, 
     116,   5,   0,   0, 228,   5, 
       0,   0,  65, 111, 110,  57, 
     216,   0,   0,   0, 216,   0, 
       0,   0,   0,   2, 255, 255, 
@@ -4133,17 +4121,17 @@ const BYTE RGBAShaderMask3D[] =
       1,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   2,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
-      1,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,  82,  68, 
      69,  70, 176,   2,   0,   0, 
       1,   0,   0,   0, 244,   0, 
@@ -4253,19 +4241,19 @@ const BYTE RGBAShaderMask3D[] =
      97, 100,   0, 118,  77,  97, 
     115, 107,  81, 117,  97, 100, 
       0,  77, 105,  99, 114, 111, 
     115, 111, 102, 116,  32,  40, 
      82,  41,  32,  72,  76,  83, 
      76,  32,  83, 104,  97, 100, 
     101, 114,  32,  67, 111, 109, 
     112, 105, 108, 101, 114,  32, 
-     57,  46,  51,  48,  46,  57, 
-     50,  48,  48,  46,  50,  48, 
-     53,  52,  54,   0,  73,  83, 
+     54,  46,  51,  46,  57,  54, 
+     48,  48,  46,  49,  54,  51, 
+     56,  52,   0, 171,  73,  83, 
      71,  78, 104,   0,   0,   0, 
       3,   0,   0,   0,   8,   0, 
       0,   0,  80,   0,   0,   0, 
       0,   0,   0,   0,   1,   0, 
       0,   0,   3,   0,   0,   0, 
       0,   0,   0,   0,  15,   0, 
       0,   0,  92,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
@@ -4286,20 +4274,19 @@ const BYTE RGBAShaderMask3D[] =
       0,   0,   0,   0,   0,   0, 
       3,   0,   0,   0,   0,   0, 
       0,   0,  15,   0,   0,   0, 
      83,  86,  95,  84,  97, 114, 
     103, 101, 116,   0, 171, 171
 };
 #if 0
 //
-// Generated by Microsoft (R) HLSL Shader Compiler 9.30.9200.20546
-//
-//
-///
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
 // Buffer Definitions: 
 //
 // cbuffer $Globals
 // {
 //
 //   float4 fLayerColor;                // Offset:    0 Size:    16 [unused]
 //   float fLayerOpacity;               // Offset:   16 Size:     4
 //   float4x4 mLayerTransform;          // Offset:   32 Size:    64 [unused]
@@ -4416,20 +4403,20 @@ mul r0.xyzw, r1.xyzw, cb0[1].xxxx
 sample r1.xyzw, v1.zwzz, t3.xyzw, s0
 mul o0.xyzw, r0.xyzw, r1.wwww
 ret 
 // Approximately 17 instruction slots used
 #endif
 
 const BYTE YCbCrShaderMask[] =
 {
-     68,  88,  66,  67, 115,  10, 
-     33,  43, 108, 217,  72,  92, 
-    140,  65,  97,  68, 194, 221, 
-     95,  25,   1,   0,   0,   0, 
+     68,  88,  66,  67, 103, 162, 
+    223, 236, 236, 142, 143, 151, 
+     73, 154, 187, 112,  81, 114, 
+    229, 251,   1,   0,   0,   0, 
     168,   8,   0,   0,   6,   0, 
       0,   0,  56,   0,   0,   0, 
      24,   2,   0,   0, 196,   4, 
       0,   0,  64,   5,   0,   0, 
       4,   8,   0,   0, 116,   8, 
       0,   0,  65, 111, 110,  57, 
     216,   1,   0,   0, 216,   1, 
       0,   0,   0,   2, 255, 255, 
@@ -4623,27 +4610,27 @@ const BYTE YCbCrShaderMask[] =
      16,   0,   0,   0,   0,   0, 
      70,  14,  16,   0,   0,   0, 
       0,   0, 246,  15,  16,   0, 
       1,   0,   0,   0,  62,   0, 
       0,   1,  83,  84,  65,  84, 
     116,   0,   0,   0,  17,   0, 
       0,   0,   3,   0,   0,   0, 
       0,   0,   0,   0,   3,   0, 
-      0,   0,   7,   0,   0,   0, 
+      0,   0,  11,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   1,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       4,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
-      0,   0,   2,   0,   0,   0, 
+      0,   0,   1,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
      82,  68,  69,  70, 188,   2, 
       0,   0,   1,   0,   0,   0, 
@@ -4755,19 +4742,19 @@ const BYTE YCbCrShaderMask[] =
      81, 117,  97, 100,   0, 118, 
      77,  97, 115, 107,  81, 117, 
      97, 100,   0,  77, 105,  99, 
     114, 111, 115, 111, 102, 116, 
      32,  40,  82,  41,  32,  72, 
      76,  83,  76,  32,  83, 104, 
      97, 100, 101, 114,  32,  67, 
     111, 109, 112, 105, 108, 101, 
-    114,  32,  57,  46,  51,  48, 
-     46,  57,  50,  48,  48,  46, 
-     50,  48,  53,  52,  54,   0, 
+    114,  32,  54,  46,  51,  46, 
+     57,  54,  48,  48,  46,  49, 
+     54,  51,  56,  52,   0, 171, 
      73,  83,  71,  78, 104,   0, 
       0,   0,   3,   0,   0,   0, 
       8,   0,   0,   0,  80,   0, 
       0,   0,   0,   0,   0,   0, 
       1,   0,   0,   0,   3,   0, 
       0,   0,   0,   0,   0,   0, 
      15,   0,   0,   0,  92,   0, 
       0,   0,   0,   0,   0,   0, 
@@ -4789,20 +4776,19 @@ const BYTE YCbCrShaderMask[] =
       0,   0,   3,   0,   0,   0, 
       0,   0,   0,   0,  15,   0, 
       0,   0,  83,  86,  95,  84, 
      97, 114, 103, 101, 116,   0, 
     171, 171
 };
 #if 0
 //
-// Generated by Microsoft (R) HLSL Shader Compiler 9.30.9200.20546
-//
-//
-///
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
 // Buffer Definitions: 
 //
 // cbuffer $Globals
 // {
 //
 //   float4 fLayerColor;                // Offset:    0 Size:    16 [unused]
 //   float fLayerOpacity;               // Offset:   16 Size:     4
 //   float4x4 mLayerTransform;          // Offset:   32 Size:    64 [unused]
@@ -4903,20 +4889,20 @@ mul r2.x, r2.w, cb0[1].x
 mul o0.xyzw, r1.xyzw, r2.xxxx
 mul o1.xyzw, r0.xyzw, r2.xxxx
 ret 
 // Approximately 10 instruction slots used
 #endif
 
 const BYTE ComponentAlphaShaderMask[] =
 {
-     68,  88,  66,  67,  66, 175, 
-    106, 103, 136,  76, 200,  80, 
-     95, 179,  74, 140, 138, 144, 
-     12,  21,   1,   0,   0,   0, 
+     68,  88,  66,  67, 245,  71, 
+    211, 223, 156, 101, 223, 204, 
+    145, 138,  53,  12,  16, 220, 
+    106,  83,   1,   0,   0,   0, 
      20,   7,   0,   0,   6,   0, 
       0,   0,  56,   0,   0,   0, 
     124,   1,   0,   0,  52,   3, 
       0,   0, 176,   3,   0,   0, 
      88,   6,   0,   0, 200,   6, 
       0,   0,  65, 111, 110,  57, 
      60,   1,   0,   0,  60,   1, 
       0,   0,   0,   2, 255, 255, 
@@ -5053,17 +5039,17 @@ const BYTE ComponentAlphaShaderMask[] =
       0,   0,   0,   0,   1,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   3,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   3,   0, 
+      0,   0,   0,   0,   1,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,  82,  68,  69,  70, 
     160,   2,   0,   0,   1,   0, 
@@ -5171,19 +5157,19 @@ const BYTE ComponentAlphaShaderMask[] =
      97, 100,   0, 118,  77,  97, 
     115, 107,  81, 117,  97, 100, 
       0,  77, 105,  99, 114, 111, 
     115, 111, 102, 116,  32,  40, 
      82,  41,  32,  72,  76,  83, 
      76,  32,  83, 104,  97, 100, 
     101, 114,  32,  67, 111, 109, 
     112, 105, 108, 101, 114,  32, 
-     57,  46,  51,  48,  46,  57, 
-     50,  48,  48,  46,  50,  48, 
-     53,  52,  54,   0,  73,  83, 
+     54,  46,  51,  46,  57,  54, 
+     48,  48,  46,  49,  54,  51, 
+     56,  52,   0, 171,  73,  83, 
      71,  78, 104,   0,   0,   0, 
       3,   0,   0,   0,   8,   0, 
       0,   0,  80,   0,   0,   0, 
       0,   0,   0,   0,   1,   0, 
       0,   0,   3,   0,   0,   0, 
       0,   0,   0,   0,  15,   0, 
       0,   0,  92,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
--- a/gfx/layers/d3d11/CompositorD3D11ShadersVR.h
+++ b/gfx/layers/d3d11/CompositorD3D11ShadersVR.h
@@ -1,638 +1,636 @@
-#if 0
-//
-// Generated by Microsoft (R) HLSL Shader Compiler 9.30.9200.20546
-//
-//
-///
-// Buffer Definitions: 
-//
-// cbuffer $Globals
-// {
-//
-//   float4 VREyeToSource;              // Offset:    0 Size:    16
-//   float4 VRDestinationScaleAndOffset;// Offset:   16 Size:    16
-//
-// }
-//
-//
-// Resource Bindings:
-//
-// Name                                 Type  Format         Dim Slot Elements
-// ------------------------------ ---------- ------- ----------- ---- --------
-// $Globals                          cbuffer      NA          NA    0        1
-//
-//
-//
-// Input signature:
-//
-// Name                 Index   Mask Register SysValue  Format   Used
-// -------------------- ----- ------ -------- -------- ------- ------
-// POSITION                 0   xy          0     NONE   float   xy  
-// TEXCOORD                 0   xy          1     NONE   float   xy  
-// TEXCOORD                 1   xy          2     NONE   float   xy  
-// TEXCOORD                 2   xy          3     NONE   float   xy  
-// COLOR                    0   xyzw        4     NONE   float   xyzw
-//
-//
-// Output signature:
-//
-// Name                 Index   Mask Register SysValue  Format   Used
-// -------------------- ----- ------ -------- -------- ------- ------
-// SV_Position              0   xyzw        0      POS   float   xyzw
-// TEXCOORD                 0   xyz         1     NONE   float   xyz 
-// TEXCOORD                 1   xyz         2     NONE   float   xyz 
-// TEXCOORD                 2   xyz         3     NONE   float   xyz 
-// COLOR                    0   xyzw        4     NONE   float   xyzw
-//
-//
-// Constant buffer to DX9 shader constant mappings:
-//
-// Target Reg Buffer  Start Reg # of Regs        Data Conversion
-// ---------- ------- --------- --------- ----------------------
-// c1         cb0             0         2  ( FLT, FLT, FLT, FLT)
-//
-//
-// Runtime generated constant mappings:
-//
-// Target Reg                               Constant Description
-// ---------- --------------------------------------------------
-// c0                              Vertex Shader position offset
-//
-//
-// Level9 shader bytecode:
-//
-    vs_2_x
-    def c3, 0.5, 1, 0, 0
-    dcl_texcoord v0
-    dcl_texcoord1 v1
-    dcl_texcoord2 v2
-    dcl_texcoord3 v3
-    dcl_texcoord4 v4
-    mad oT0.xy, c1, v1, c1.zwzw
-    mad oT1.xy, c1, v2, c1.zwzw
-    mad oT2.xy, c1, v3, c1.zwzw
-    mad r0.xy, v0, c2.zwzw, c2
-    add oPos.xy, r0, c0
-    mov oPos.zw, c3.xyxy
-    mov oT0.z, c3.y
-    mov oT1.z, c3.y
-    mov oT2.z, c3.y
-    mov oT3, v4
-
-// approximately 10 instruction slots used
-vs_4_0
-dcl_constantbuffer cb0[2], immediateIndexed
-dcl_input v0.xy
-dcl_input v1.xy
-dcl_input v2.xy
-dcl_input v3.xy
-dcl_input v4.xyzw
-dcl_output_siv o0.xyzw, position
-dcl_output o1.xyz
-dcl_output o2.xyz
-dcl_output o3.xyz
-dcl_output o4.xyzw
-mad o0.xy, v0.xyxx, cb0[1].zwzz, cb0[1].xyxx
-mov o0.zw, l(0,0,0.500000,1.000000)
-mad o1.xy, cb0[0].xyxx, v1.xyxx, cb0[0].zwzz
-mov o1.z, l(1.000000)
-mad o2.xy, cb0[0].xyxx, v2.xyxx, cb0[0].zwzz
-mov o2.z, l(1.000000)
-mad o3.xy, cb0[0].xyxx, v3.xyxx, cb0[0].zwzz
-mov o3.z, l(1.000000)
-mov o4.xyzw, v4.xyzw
-ret 
-// Approximately 10 instruction slots used
-#endif
-
-const BYTE OculusVRDistortionVS[] =
-{
-     68,  88,  66,  67, 146, 215, 
-     61, 238,  94,   6,  58,  25, 
-     65, 203, 120, 251,  26,  22, 
-    109,   4,   1,   0,   0,   0, 
-    244,   5,   0,   0,   6,   0, 
-      0,   0,  56,   0,   0,   0, 
-    108,   1,   0,   0,  44,   3, 
-      0,   0, 168,   3,   0,   0, 
-    176,   4,   0,   0,  80,   5, 
-      0,   0,  65, 111, 110,  57, 
-     44,   1,   0,   0,  44,   1, 
-      0,   0,   0,   2, 254, 255, 
-    248,   0,   0,   0,  52,   0, 
-      0,   0,   1,   0,  36,   0, 
-      0,   0,  48,   0,   0,   0, 
-     48,   0,   0,   0,  36,   0, 
-      1,   0,  48,   0,   0,   0, 
-      0,   0,   2,   0,   1,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   1,   2, 254, 255, 
-     81,   0,   0,   5,   3,   0, 
-     15, 160,   0,   0,   0,  63, 
-      0,   0, 128,  63,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-     31,   0,   0,   2,   5,   0, 
-      0, 128,   0,   0,  15, 144, 
-     31,   0,   0,   2,   5,   0, 
-      1, 128,   1,   0,  15, 144, 
-     31,   0,   0,   2,   5,   0, 
-      2, 128,   2,   0,  15, 144, 
-     31,   0,   0,   2,   5,   0, 
-      3, 128,   3,   0,  15, 144, 
-     31,   0,   0,   2,   5,   0, 
-      4, 128,   4,   0,  15, 144, 
-      4,   0,   0,   4,   0,   0, 
-      3, 224,   1,   0, 228, 160, 
-      1,   0, 228, 144,   1,   0, 
-    238, 160,   4,   0,   0,   4, 
-      1,   0,   3, 224,   1,   0, 
-    228, 160,   2,   0, 228, 144, 
-      1,   0, 238, 160,   4,   0, 
-      0,   4,   2,   0,   3, 224, 
-      1,   0, 228, 160,   3,   0, 
-    228, 144,   1,   0, 238, 160, 
-      4,   0,   0,   4,   0,   0, 
-      3, 128,   0,   0, 228, 144, 
-      2,   0, 238, 160,   2,   0, 
-    228, 160,   2,   0,   0,   3, 
-      0,   0,   3, 192,   0,   0, 
-    228, 128,   0,   0, 228, 160, 
-      1,   0,   0,   2,   0,   0, 
-     12, 192,   3,   0,  68, 160, 
-      1,   0,   0,   2,   0,   0, 
-      4, 224,   3,   0,  85, 160, 
-      1,   0,   0,   2,   1,   0, 
-      4, 224,   3,   0,  85, 160, 
-      1,   0,   0,   2,   2,   0, 
-      4, 224,   3,   0,  85, 160, 
-      1,   0,   0,   2,   3,   0, 
-     15, 224,   4,   0, 228, 144, 
-    255, 255,   0,   0,  83,  72, 
-     68,  82, 184,   1,   0,   0, 
-     64,   0,   1,   0, 110,   0, 
-      0,   0,  89,   0,   0,   4, 
-     70, 142,  32,   0,   0,   0, 
-      0,   0,   2,   0,   0,   0, 
-     95,   0,   0,   3,  50,  16, 
-     16,   0,   0,   0,   0,   0, 
-     95,   0,   0,   3,  50,  16, 
-     16,   0,   1,   0,   0,   0, 
-     95,   0,   0,   3,  50,  16, 
-     16,   0,   2,   0,   0,   0, 
-     95,   0,   0,   3,  50,  16, 
-     16,   0,   3,   0,   0,   0, 
-     95,   0,   0,   3, 242,  16, 
-     16,   0,   4,   0,   0,   0, 
-    103,   0,   0,   4, 242,  32, 
-     16,   0,   0,   0,   0,   0, 
-      1,   0,   0,   0, 101,   0, 
-      0,   3, 114,  32,  16,   0, 
-      1,   0,   0,   0, 101,   0, 
-      0,   3, 114,  32,  16,   0, 
-      2,   0,   0,   0, 101,   0, 
-      0,   3, 114,  32,  16,   0, 
-      3,   0,   0,   0, 101,   0, 
-      0,   3, 242,  32,  16,   0, 
-      4,   0,   0,   0,  50,   0, 
-      0,  11,  50,  32,  16,   0, 
-      0,   0,   0,   0,  70,  16, 
-     16,   0,   0,   0,   0,   0, 
-    230, 138,  32,   0,   0,   0, 
-      0,   0,   1,   0,   0,   0, 
-     70, 128,  32,   0,   0,   0, 
-      0,   0,   1,   0,   0,   0, 
-     54,   0,   0,   8, 194,  32, 
-     16,   0,   0,   0,   0,   0, 
-      2,  64,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,  63,   0,   0, 
-    128,  63,  50,   0,   0,  11, 
-     50,  32,  16,   0,   1,   0, 
-      0,   0,  70, 128,  32,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,  70,  16,  16,   0, 
-      1,   0,   0,   0, 230, 138, 
-     32,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,  54,   0, 
-      0,   5,  66,  32,  16,   0, 
-      1,   0,   0,   0,   1,  64, 
-      0,   0,   0,   0, 128,  63, 
-     50,   0,   0,  11,  50,  32, 
-     16,   0,   2,   0,   0,   0, 
-     70, 128,  32,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-     70,  16,  16,   0,   2,   0, 
-      0,   0, 230, 138,  32,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,  54,   0,   0,   5, 
-     66,  32,  16,   0,   2,   0, 
-      0,   0,   1,  64,   0,   0, 
-      0,   0, 128,  63,  50,   0, 
-      0,  11,  50,  32,  16,   0, 
-      3,   0,   0,   0,  70, 128, 
-     32,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,  70,  16, 
-     16,   0,   3,   0,   0,   0, 
-    230, 138,  32,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-     54,   0,   0,   5,  66,  32, 
-     16,   0,   3,   0,   0,   0, 
-      1,  64,   0,   0,   0,   0, 
-    128,  63,  54,   0,   0,   5, 
-    242,  32,  16,   0,   4,   0, 
-      0,   0,  70,  30,  16,   0, 
-      4,   0,   0,   0,  62,   0, 
-      0,   1,  83,  84,  65,  84, 
-    116,   0,   0,   0,  10,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,  10,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   1,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   6,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-     82,  68,  69,  70,   0,   1, 
-      0,   0,   1,   0,   0,   0, 
-     72,   0,   0,   0,   1,   0, 
-      0,   0,  28,   0,   0,   0, 
-      0,   4, 254, 255,   0,   1, 
-      0,   0, 204,   0,   0,   0, 
-     60,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      1,   0,   0,   0,   0,   0, 
-      0,   0,  36,  71, 108, 111, 
-     98,  97, 108, 115,   0, 171, 
-    171, 171,  60,   0,   0,   0, 
-      2,   0,   0,   0,  96,   0, 
-      0,   0,  32,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0, 144,   0,   0,   0, 
-      0,   0,   0,   0,  16,   0, 
-      0,   0,   2,   0,   0,   0, 
-    160,   0,   0,   0,   0,   0, 
-      0,   0, 176,   0,   0,   0, 
-     16,   0,   0,   0,  16,   0, 
-      0,   0,   2,   0,   0,   0, 
-    160,   0,   0,   0,   0,   0, 
-      0,   0,  86,  82,  69, 121, 
-    101,  84, 111,  83, 111, 117, 
-    114,  99, 101,   0, 171, 171, 
-      1,   0,   3,   0,   1,   0, 
-      4,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,  86,  82, 
-     68, 101, 115, 116, 105, 110, 
-     97, 116, 105, 111, 110,  83, 
-     99,  97, 108, 101,  65, 110, 
-    100,  79, 102, 102, 115, 101, 
-    116,   0,  77, 105,  99, 114, 
-    111, 115, 111, 102, 116,  32, 
-     40,  82,  41,  32,  72,  76, 
-     83,  76,  32,  83, 104,  97, 
-    100, 101, 114,  32,  67, 111, 
-    109, 112, 105, 108, 101, 114, 
-     32,  57,  46,  51,  48,  46, 
-     57,  50,  48,  48,  46,  50, 
-     48,  53,  52,  54,   0, 171, 
-     73,  83,  71,  78, 152,   0, 
-      0,   0,   5,   0,   0,   0, 
-      8,   0,   0,   0, 128,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   3,   0, 
-      0,   0,   0,   0,   0,   0, 
-      3,   3,   0,   0, 137,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   3,   0, 
-      0,   0,   1,   0,   0,   0, 
-      3,   3,   0,   0, 137,   0, 
-      0,   0,   1,   0,   0,   0, 
-      0,   0,   0,   0,   3,   0, 
-      0,   0,   2,   0,   0,   0, 
-      3,   3,   0,   0, 137,   0, 
-      0,   0,   2,   0,   0,   0, 
-      0,   0,   0,   0,   3,   0, 
-      0,   0,   3,   0,   0,   0, 
-      3,   3,   0,   0, 146,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   3,   0, 
-      0,   0,   4,   0,   0,   0, 
-     15,  15,   0,   0,  80,  79, 
-     83,  73,  84,  73,  79,  78, 
-      0,  84,  69,  88,  67,  79, 
-     79,  82,  68,   0,  67,  79, 
-     76,  79,  82,   0,  79,  83, 
-     71,  78, 156,   0,   0,   0, 
-      5,   0,   0,   0,   8,   0, 
-      0,   0, 128,   0,   0,   0, 
-      0,   0,   0,   0,   1,   0, 
-      0,   0,   3,   0,   0,   0, 
-      0,   0,   0,   0,  15,   0, 
-      0,   0, 140,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   3,   0,   0,   0, 
-      1,   0,   0,   0,   7,   8, 
-      0,   0, 140,   0,   0,   0, 
-      1,   0,   0,   0,   0,   0, 
-      0,   0,   3,   0,   0,   0, 
-      2,   0,   0,   0,   7,   8, 
-      0,   0, 140,   0,   0,   0, 
-      2,   0,   0,   0,   0,   0, 
-      0,   0,   3,   0,   0,   0, 
-      3,   0,   0,   0,   7,   8, 
-      0,   0, 149,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   3,   0,   0,   0, 
-      4,   0,   0,   0,  15,   0, 
-      0,   0,  83,  86,  95,  80, 
-    111, 115, 105, 116, 105, 111, 
-    110,   0,  84,  69,  88,  67, 
-     79,  79,  82,  68,   0,  67, 
-     79,  76,  79,  82,   0, 171
-};
-#if 0
-//
-// Generated by Microsoft (R) HLSL Shader Compiler 9.30.9200.20546
-//
-//
-///
-// Resource Bindings:
-//
-// Name                                 Type  Format         Dim Slot Elements
-// ------------------------------ ---------- ------- ----------- ---- --------
-// Linear                            sampler      NA          NA    0        1
-// Texture                           texture  float4          2d    0        1
-//
-//
-//
-// Input signature:
-//
-// Name                 Index   Mask Register SysValue  Format   Used
-// -------------------- ----- ------ -------- -------- ------- ------
-// SV_Position              0   xyzw        0      POS   float       
-// TEXCOORD                 0   xyz         1     NONE   float   xy  
-// TEXCOORD                 1   xyz         2     NONE   float   xy  
-// TEXCOORD                 2   xyz         3     NONE   float   xy  
-// COLOR                    0   xyzw        4     NONE   float   x   
-//
-//
-// Output signature:
-//
-// Name                 Index   Mask Register SysValue  Format   Used
-// -------------------- ----- ------ -------- -------- ------- ------
-// SV_Target                0   xyzw        0   TARGET   float   xyzw
-//
-//
-// Sampler/Resource to DX9 shader sampler mappings:
-//
-// Target Sampler Source Sampler  Source Resource
-// -------------- --------------- ----------------
-// s0             s0              t0               
-//
-//
-// Level9 shader bytecode:
-//
-    ps_2_x
-    def c0, 1, 0, 0, 0
-    dcl t0.xyz
-    dcl t1.xyz
-    dcl t2.xyz
-    dcl t3
-    dcl_2d s0
-    texld r0, t1, s0
-    texld r1, t0, s0
-    mul r1.x, r1.x, t3.x
-    mul r1.y, r0.y, t3.x
-    texld r0, t2, s0
-    mul r1.z, r0.z, t3.x
-    mov r1.w, c0.x
-    mov oC0, r1
-
-// approximately 8 instruction slots used (3 texture, 5 arithmetic)
-ps_4_0
-dcl_sampler s0, mode_default
-dcl_resource_texture2d (float,float,float,float) t0
-dcl_input_ps linear v1.xy
-dcl_input_ps linear v2.xy
-dcl_input_ps linear v3.xy
-dcl_input_ps linear v4.x
-dcl_output o0.xyzw
-dcl_temps 1
-sample r0.xyzw, v1.xyxx, t0.xyzw, s0
-mul o0.x, r0.x, v4.x
-sample r0.xyzw, v2.xyxx, t0.xyzw, s0
-mul o0.y, r0.y, v4.x
-sample r0.xyzw, v3.xyxx, t0.xyzw, s0
-mul o0.z, r0.z, v4.x
-mov o0.w, l(1.000000)
-ret 
-// Approximately 8 instruction slots used
-#endif
-
-const BYTE OculusVRDistortionPS[] =
-{
-     68,  88,  66,  67, 150, 176, 
-     84, 101, 196,  27,  87, 110, 
-    226, 144, 161,  15,  69,  81, 
-     48, 158,   1,   0,   0,   0, 
-    128,   4,   0,   0,   6,   0, 
-      0,   0,  56,   0,   0,   0, 
-     60,   1,   0,   0, 132,   2, 
-      0,   0,   0,   3,   0,   0, 
-    168,   3,   0,   0,  76,   4, 
-      0,   0,  65, 111, 110,  57, 
-    252,   0,   0,   0, 252,   0, 
-      0,   0,   0,   2, 255, 255, 
-    212,   0,   0,   0,  40,   0, 
-      0,   0,   0,   0,  40,   0, 
-      0,   0,  40,   0,   0,   0, 
-     40,   0,   1,   0,  36,   0, 
-      0,   0,  40,   0,   0,   0, 
-      0,   0,   1,   2, 255, 255, 
-     81,   0,   0,   5,   0,   0, 
-     15, 160,   0,   0, 128,  63, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-     31,   0,   0,   2,   0,   0, 
-      0, 128,   0,   0,   7, 176, 
-     31,   0,   0,   2,   0,   0, 
-      0, 128,   1,   0,   7, 176, 
-     31,   0,   0,   2,   0,   0, 
-      0, 128,   2,   0,   7, 176, 
-     31,   0,   0,   2,   0,   0, 
-      0, 128,   3,   0,  15, 176, 
-     31,   0,   0,   2,   0,   0, 
-      0, 144,   0,   8,  15, 160, 
-     66,   0,   0,   3,   0,   0, 
-     15, 128,   1,   0, 228, 176, 
-      0,   8, 228, 160,  66,   0, 
-      0,   3,   1,   0,  15, 128, 
-      0,   0, 228, 176,   0,   8, 
-    228, 160,   5,   0,   0,   3, 
-      1,   0,   1, 128,   1,   0, 
-      0, 128,   3,   0,   0, 176, 
-      5,   0,   0,   3,   1,   0, 
-      2, 128,   0,   0,  85, 128, 
-      3,   0,   0, 176,  66,   0, 
-      0,   3,   0,   0,  15, 128, 
-      2,   0, 228, 176,   0,   8, 
-    228, 160,   5,   0,   0,   3, 
-      1,   0,   4, 128,   0,   0, 
-    170, 128,   3,   0,   0, 176, 
-      1,   0,   0,   2,   1,   0, 
-      8, 128,   0,   0,   0, 160, 
-      1,   0,   0,   2,   0,   8, 
-     15, 128,   1,   0, 228, 128, 
-    255, 255,   0,   0,  83,  72, 
-     68,  82,  64,   1,   0,   0, 
-     64,   0,   0,   0,  80,   0, 
-      0,   0,  90,   0,   0,   3, 
-      0,  96,  16,   0,   0,   0, 
-      0,   0,  88,  24,   0,   4, 
-      0, 112,  16,   0,   0,   0, 
-      0,   0,  85,  85,   0,   0, 
-     98,  16,   0,   3,  50,  16, 
-     16,   0,   1,   0,   0,   0, 
-     98,  16,   0,   3,  50,  16, 
-     16,   0,   2,   0,   0,   0, 
-     98,  16,   0,   3,  50,  16, 
-     16,   0,   3,   0,   0,   0, 
-     98,  16,   0,   3,  18,  16, 
-     16,   0,   4,   0,   0,   0, 
-    101,   0,   0,   3, 242,  32, 
-     16,   0,   0,   0,   0,   0, 
-    104,   0,   0,   2,   1,   0, 
-      0,   0,  69,   0,   0,   9, 
-    242,   0,  16,   0,   0,   0, 
-      0,   0,  70,  16,  16,   0, 
-      1,   0,   0,   0,  70, 126, 
-     16,   0,   0,   0,   0,   0, 
-      0,  96,  16,   0,   0,   0, 
-      0,   0,  56,   0,   0,   7, 
-     18,  32,  16,   0,   0,   0, 
-      0,   0,  10,   0,  16,   0, 
-      0,   0,   0,   0,  10,  16, 
-     16,   0,   4,   0,   0,   0, 
-     69,   0,   0,   9, 242,   0, 
-     16,   0,   0,   0,   0,   0, 
-     70,  16,  16,   0,   2,   0, 
-      0,   0,  70, 126,  16,   0, 
-      0,   0,   0,   0,   0,  96, 
-     16,   0,   0,   0,   0,   0, 
-     56,   0,   0,   7,  34,  32, 
-     16,   0,   0,   0,   0,   0, 
-     26,   0,  16,   0,   0,   0, 
-      0,   0,  10,  16,  16,   0, 
-      4,   0,   0,   0,  69,   0, 
-      0,   9, 242,   0,  16,   0, 
-      0,   0,   0,   0,  70,  16, 
-     16,   0,   3,   0,   0,   0, 
-     70, 126,  16,   0,   0,   0, 
-      0,   0,   0,  96,  16,   0, 
-      0,   0,   0,   0,  56,   0, 
-      0,   7,  66,  32,  16,   0, 
-      0,   0,   0,   0,  42,   0, 
-     16,   0,   0,   0,   0,   0, 
-     10,  16,  16,   0,   4,   0, 
-      0,   0,  54,   0,   0,   5, 
-    130,  32,  16,   0,   0,   0, 
-      0,   0,   1,  64,   0,   0, 
-      0,   0, 128,  63,  62,   0, 
-      0,   1,  83,  84,  65,  84, 
-    116,   0,   0,   0,   8,   0, 
-      0,   0,   1,   0,   0,   0, 
-      0,   0,   0,   0,   5,   0, 
-      0,   0,   3,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   1,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      3,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   2,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-     82,  68,  69,  70, 160,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   2,   0, 
-      0,   0,  28,   0,   0,   0, 
-      0,   4, 255, 255,   0,   1, 
-      0,   0, 107,   0,   0,   0, 
-     92,   0,   0,   0,   3,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      1,   0,   0,   0,   0,   0, 
-      0,   0,  99,   0,   0,   0, 
-      2,   0,   0,   0,   5,   0, 
-      0,   0,   4,   0,   0,   0, 
-    255, 255, 255, 255,   0,   0, 
-      0,   0,   1,   0,   0,   0, 
-     13,   0,   0,   0,  76, 105, 
-    110, 101,  97, 114,   0,  84, 
-    101, 120, 116, 117, 114, 101, 
-      0,  77, 105,  99, 114, 111, 
-    115, 111, 102, 116,  32,  40, 
-     82,  41,  32,  72,  76,  83, 
-     76,  32,  83, 104,  97, 100, 
-    101, 114,  32,  67, 111, 109, 
-    112, 105, 108, 101, 114,  32, 
-     57,  46,  51,  48,  46,  57, 
-     50,  48,  48,  46,  50,  48, 
-     53,  52,  54,   0, 171, 171, 
-     73,  83,  71,  78, 156,   0, 
-      0,   0,   5,   0,   0,   0, 
-      8,   0,   0,   0, 128,   0, 
-      0,   0,   0,   0,   0,   0, 
-      1,   0,   0,   0,   3,   0, 
-      0,   0,   0,   0,   0,   0, 
-     15,   0,   0,   0, 140,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   3,   0, 
-      0,   0,   1,   0,   0,   0, 
-      7,   3,   0,   0, 140,   0, 
-      0,   0,   1,   0,   0,   0, 
-      0,   0,   0,   0,   3,   0, 
-      0,   0,   2,   0,   0,   0, 
-      7,   3,   0,   0, 140,   0, 
-      0,   0,   2,   0,   0,   0, 
-      0,   0,   0,   0,   3,   0, 
-      0,   0,   3,   0,   0,   0, 
-      7,   3,   0,   0, 149,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   3,   0, 
-      0,   0,   4,   0,   0,   0, 
-     15,   1,   0,   0,  83,  86, 
-     95,  80, 111, 115, 105, 116, 
-    105, 111, 110,   0,  84,  69, 
-     88,  67,  79,  79,  82,  68, 
-      0,  67,  79,  76,  79,  82, 
-      0, 171,  79,  83,  71,  78, 
-     44,   0,   0,   0,   1,   0, 
-      0,   0,   8,   0,   0,   0, 
-     32,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      3,   0,   0,   0,   0,   0, 
-      0,   0,  15,   0,   0,   0, 
-     83,  86,  95,  84,  97, 114, 
-    103, 101, 116,   0, 171, 171
-};
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Buffer Definitions: 
+//
+// cbuffer $Globals
+// {
+//
+//   float4 VREyeToSource;              // Offset:    0 Size:    16
+//   float4 VRDestinationScaleAndOffset;// Offset:   16 Size:    16
+//
+// }
+//
+//
+// Resource Bindings:
+//
+// Name                                 Type  Format         Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// $Globals                          cbuffer      NA          NA    0        1
+//
+//
+//
+// Input signature:
+//
+// Name                 Index   Mask Register SysValue  Format   Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// POSITION                 0   xy          0     NONE   float   xy  
+// TEXCOORD                 0   xy          1     NONE   float   xy  
+// TEXCOORD                 1   xy          2     NONE   float   xy  
+// TEXCOORD                 2   xy          3     NONE   float   xy  
+// COLOR                    0   xyzw        4     NONE   float   xyzw
+//
+//
+// Output signature:
+//
+// Name                 Index   Mask Register SysValue  Format   Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_Position              0   xyzw        0      POS   float   xyzw
+// TEXCOORD                 0   xyz         1     NONE   float   xyz 
+// TEXCOORD                 1   xyz         2     NONE   float   xyz 
+// TEXCOORD                 2   xyz         3     NONE   float   xyz 
+// COLOR                    0   xyzw        4     NONE   float   xyzw
+//
+//
+// Constant buffer to DX9 shader constant mappings:
+//
+// Target Reg Buffer  Start Reg # of Regs        Data Conversion
+// ---------- ------- --------- --------- ----------------------
+// c1         cb0             0         2  ( FLT, FLT, FLT, FLT)
+//
+//
+// Runtime generated constant mappings:
+//
+// Target Reg                               Constant Description
+// ---------- --------------------------------------------------
+// c0                              Vertex Shader position offset
+//
+//
+// Level9 shader bytecode:
+//
+    vs_2_x
+    def c3, 0.5, 1, 0, 0
+    dcl_texcoord v0
+    dcl_texcoord1 v1
+    dcl_texcoord2 v2
+    dcl_texcoord3 v3
+    dcl_texcoord4 v4
+    mad oT0.xy, v1, c1.zwzw, c1
+    mad oT1.xy, v2, c1.zwzw, c1
+    mad oT2.xy, v3, c1.zwzw, c1
+    mad r0.xy, v0, c2.zwzw, c2
+    add oPos.xy, r0, c0
+    mov oPos.zw, c3.xyxy
+    mov oT0.z, c3.y
+    mov oT1.z, c3.y
+    mov oT2.z, c3.y
+    mov oT3, v4
+
+// approximately 10 instruction slots used
+vs_4_0
+dcl_constantbuffer cb0[2], immediateIndexed
+dcl_input v0.xy
+dcl_input v1.xy
+dcl_input v2.xy
+dcl_input v3.xy
+dcl_input v4.xyzw
+dcl_output_siv o0.xyzw, position
+dcl_output o1.xyz
+dcl_output o2.xyz
+dcl_output o3.xyz
+dcl_output o4.xyzw
+mad o0.xy, v0.xyxx, cb0[1].zwzz, cb0[1].xyxx
+mov o0.zw, l(0,0,0.500000,1.000000)
+mad o1.xy, v1.xyxx, cb0[0].zwzz, cb0[0].xyxx
+mov o1.z, l(1.000000)
+mad o2.xy, v2.xyxx, cb0[0].zwzz, cb0[0].xyxx
+mov o2.z, l(1.000000)
+mad o3.xy, v3.xyxx, cb0[0].zwzz, cb0[0].xyxx
+mov o3.z, l(1.000000)
+mov o4.xyzw, v4.xyzw
+ret 
+// Approximately 10 instruction slots used
+#endif
+
+const BYTE OculusVRDistortionVS[] =
+{
+     68,  88,  66,  67,   3,  61, 
+    196, 122,  10,  53,  44, 234, 
+     18, 242, 195, 238,  42,  90, 
+     72, 193,   1,   0,   0,   0, 
+    244,   5,   0,   0,   6,   0, 
+      0,   0,  56,   0,   0,   0, 
+    108,   1,   0,   0,  44,   3, 
+      0,   0, 168,   3,   0,   0, 
+    176,   4,   0,   0,  80,   5, 
+      0,   0,  65, 111, 110,  57, 
+     44,   1,   0,   0,  44,   1, 
+      0,   0,   0,   2, 254, 255, 
+    248,   0,   0,   0,  52,   0, 
+      0,   0,   1,   0,  36,   0, 
+      0,   0,  48,   0,   0,   0, 
+     48,   0,   0,   0,  36,   0, 
+      1,   0,  48,   0,   0,   0, 
+      0,   0,   2,   0,   1,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   1,   2, 254, 255, 
+     81,   0,   0,   5,   3,   0, 
+     15, 160,   0,   0,   0,  63, 
+      0,   0, 128,  63,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+     31,   0,   0,   2,   5,   0, 
+      0, 128,   0,   0,  15, 144, 
+     31,   0,   0,   2,   5,   0, 
+      1, 128,   1,   0,  15, 144, 
+     31,   0,   0,   2,   5,   0, 
+      2, 128,   2,   0,  15, 144, 
+     31,   0,   0,   2,   5,   0, 
+      3, 128,   3,   0,  15, 144, 
+     31,   0,   0,   2,   5,   0, 
+      4, 128,   4,   0,  15, 144, 
+      4,   0,   0,   4,   0,   0, 
+      3, 224,   1,   0, 228, 144, 
+      1,   0, 238, 160,   1,   0, 
+    228, 160,   4,   0,   0,   4, 
+      1,   0,   3, 224,   2,   0, 
+    228, 144,   1,   0, 238, 160, 
+      1,   0, 228, 160,   4,   0, 
+      0,   4,   2,   0,   3, 224, 
+      3,   0, 228, 144,   1,   0, 
+    238, 160,   1,   0, 228, 160, 
+      4,   0,   0,   4,   0,   0, 
+      3, 128,   0,   0, 228, 144, 
+      2,   0, 238, 160,   2,   0, 
+    228, 160,   2,   0,   0,   3, 
+      0,   0,   3, 192,   0,   0, 
+    228, 128,   0,   0, 228, 160, 
+      1,   0,   0,   2,   0,   0, 
+     12, 192,   3,   0,  68, 160, 
+      1,   0,   0,   2,   0,   0, 
+      4, 224,   3,   0,  85, 160, 
+      1,   0,   0,   2,   1,   0, 
+      4, 224,   3,   0,  85, 160, 
+      1,   0,   0,   2,   2,   0, 
+      4, 224,   3,   0,  85, 160, 
+      1,   0,   0,   2,   3,   0, 
+     15, 224,   4,   0, 228, 144, 
+    255, 255,   0,   0,  83,  72, 
+     68,  82, 184,   1,   0,   0, 
+     64,   0,   1,   0, 110,   0, 
+      0,   0,  89,   0,   0,   4, 
+     70, 142,  32,   0,   0,   0, 
+      0,   0,   2,   0,   0,   0, 
+     95,   0,   0,   3,  50,  16, 
+     16,   0,   0,   0,   0,   0, 
+     95,   0,   0,   3,  50,  16, 
+     16,   0,   1,   0,   0,   0, 
+     95,   0,   0,   3,  50,  16, 
+     16,   0,   2,   0,   0,   0, 
+     95,   0,   0,   3,  50,  16, 
+     16,   0,   3,   0,   0,   0, 
+     95,   0,   0,   3, 242,  16, 
+     16,   0,   4,   0,   0,   0, 
+    103,   0,   0,   4, 242,  32, 
+     16,   0,   0,   0,   0,   0, 
+      1,   0,   0,   0, 101,   0, 
+      0,   3, 114,  32,  16,   0, 
+      1,   0,   0,   0, 101,   0, 
+      0,   3, 114,  32,  16,   0, 
+      2,   0,   0,   0, 101,   0, 
+      0,   3, 114,  32,  16,   0, 
+      3,   0,   0,   0, 101,   0, 
+      0,   3, 242,  32,  16,   0, 
+      4,   0,   0,   0,  50,   0, 
+      0,  11,  50,  32,  16,   0, 
+      0,   0,   0,   0,  70,  16, 
+     16,   0,   0,   0,   0,   0, 
+    230, 138,  32,   0,   0,   0, 
+      0,   0,   1,   0,   0,   0, 
+     70, 128,  32,   0,   0,   0, 
+      0,   0,   1,   0,   0,   0, 
+     54,   0,   0,   8, 194,  32, 
+     16,   0,   0,   0,   0,   0, 
+      2,  64,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,  63,   0,   0, 
+    128,  63,  50,   0,   0,  11, 
+     50,  32,  16,   0,   1,   0, 
+      0,   0,  70,  16,  16,   0, 
+      1,   0,   0,   0, 230, 138, 
+     32,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,  70, 128, 
+     32,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,  54,   0, 
+      0,   5,  66,  32,  16,   0, 
+      1,   0,   0,   0,   1,  64, 
+      0,   0,   0,   0, 128,  63, 
+     50,   0,   0,  11,  50,  32, 
+     16,   0,   2,   0,   0,   0, 
+     70,  16,  16,   0,   2,   0, 
+      0,   0, 230, 138,  32,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,  70, 128,  32,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,  54,   0,   0,   5, 
+     66,  32,  16,   0,   2,   0, 
+      0,   0,   1,  64,   0,   0, 
+      0,   0, 128,  63,  50,   0, 
+      0,  11,  50,  32,  16,   0, 
+      3,   0,   0,   0,  70,  16, 
+     16,   0,   3,   0,   0,   0, 
+    230, 138,  32,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+     70, 128,  32,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+     54,   0,   0,   5,  66,  32, 
+     16,   0,   3,   0,   0,   0, 
+      1,  64,   0,   0,   0,   0, 
+    128,  63,  54,   0,   0,   5, 
+    242,  32,  16,   0,   4,   0, 
+      0,   0,  70,  30,  16,   0, 
+      4,   0,   0,   0,  62,   0, 
+      0,   1,  83,  84,  65,  84, 
+    116,   0,   0,   0,  10,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,  10,   0, 
+      0,   0,   4,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   1,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   5,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+     82,  68,  69,  70,   0,   1, 
+      0,   0,   1,   0,   0,   0, 
+     72,   0,   0,   0,   1,   0, 
+      0,   0,  28,   0,   0,   0, 
+      0,   4, 254, 255,   0,   1, 
+      0,   0, 204,   0,   0,   0, 
+     60,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      1,   0,   0,   0,   0,   0, 
+      0,   0,  36,  71, 108, 111, 
+     98,  97, 108, 115,   0, 171, 
+    171, 171,  60,   0,   0,   0, 
+      2,   0,   0,   0,  96,   0, 
+      0,   0,  32,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0, 144,   0,   0,   0, 
+      0,   0,   0,   0,  16,   0, 
+      0,   0,   2,   0,   0,   0, 
+    160,   0,   0,   0,   0,   0, 
+      0,   0, 176,   0,   0,   0, 
+     16,   0,   0,   0,  16,   0, 
+      0,   0,   2,   0,   0,   0, 
+    160,   0,   0,   0,   0,   0, 
+      0,   0,  86,  82,  69, 121, 
+    101,  84, 111,  83, 111, 117, 
+    114,  99, 101,   0, 171, 171, 
+      1,   0,   3,   0,   1,   0, 
+      4,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,  86,  82, 
+     68, 101, 115, 116, 105, 110, 
+     97, 116, 105, 111, 110,  83, 
+     99,  97, 108, 101,  65, 110, 
+    100,  79, 102, 102, 115, 101, 
+    116,   0,  77, 105,  99, 114, 
+    111, 115, 111, 102, 116,  32, 
+     40,  82,  41,  32,  72,  76, 
+     83,  76,  32,  83, 104,  97, 
+    100, 101, 114,  32,  67, 111, 
+    109, 112, 105, 108, 101, 114, 
+     32,  54,  46,  51,  46,  57, 
+     54,  48,  48,  46,  49,  54, 
+     51,  56,  52,   0, 171, 171, 
+     73,  83,  71,  78, 152,   0, 
+      0,   0,   5,   0,   0,   0, 
+      8,   0,   0,   0, 128,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   3,   0, 
+      0,   0,   0,   0,   0,   0, 
+      3,   3,   0,   0, 137,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   3,   0, 
+      0,   0,   1,   0,   0,   0, 
+      3,   3,   0,   0, 137,   0, 
+      0,   0,   1,   0,   0,   0, 
+      0,   0,   0,   0,   3,   0, 
+      0,   0,   2,   0,   0,   0, 
+      3,   3,   0,   0, 137,   0, 
+      0,   0,   2,   0,   0,   0, 
+      0,   0,   0,   0,   3,   0, 
+      0,   0,   3,   0,   0,   0, 
+      3,   3,   0,   0, 146,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   3,   0, 
+      0,   0,   4,   0,   0,   0, 
+     15,  15,   0,   0,  80,  79, 
+     83,  73,  84,  73,  79,  78, 
+      0,  84,  69,  88,  67,  79, 
+     79,  82,  68,   0,  67,  79, 
+     76,  79,  82,   0,  79,  83, 
+     71,  78, 156,   0,   0,   0, 
+      5,   0,   0,   0,   8,   0, 
+      0,   0, 128,   0,   0,   0, 
+      0,   0,   0,   0,   1,   0, 
+      0,   0,   3,   0,   0,   0, 
+      0,   0,   0,   0,  15,   0, 
+      0,   0, 140,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   3,   0,   0,   0, 
+      1,   0,   0,   0,   7,   8, 
+      0,   0, 140,   0,   0,   0, 
+      1,   0,   0,   0,   0,   0, 
+      0,   0,   3,   0,   0,   0, 
+      2,   0,   0,   0,   7,   8, 
+      0,   0, 140,   0,   0,   0, 
+      2,   0,   0,   0,   0,   0, 
+      0,   0,   3,   0,   0,   0, 
+      3,   0,   0,   0,   7,   8, 
+      0,   0, 149,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   3,   0,   0,   0, 
+      4,   0,   0,   0,  15,   0, 
+      0,   0,  83,  86,  95,  80, 
+    111, 115, 105, 116, 105, 111, 
+    110,   0,  84,  69,  88,  67, 
+     79,  79,  82,  68,   0,  67, 
+     79,  76,  79,  82,   0, 171
+};
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+//
+// Resource Bindings:
+//
+// Name                                 Type  Format         Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// Linear                            sampler      NA          NA    0        1
+// Texture                           texture  float4          2d    0        1
+//
+//
+//
+// Input signature:
+//
+// Name                 Index   Mask Register SysValue  Format   Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_Position              0   xyzw        0      POS   float       
+// TEXCOORD                 0   xyz         1     NONE   float   xy  
+// TEXCOORD                 1   xyz         2     NONE   float   xy  
+// TEXCOORD                 2   xyz         3     NONE   float   xy  
+// COLOR                    0   xyzw        4     NONE   float   x   
+//
+//
+// Output signature:
+//
+// Name                 Index   Mask Register SysValue  Format   Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_Target                0   xyzw        0   TARGET   float   xyzw
+//
+//
+// Sampler/Resource to DX9 shader sampler mappings:
+//
+// Target Sampler Source Sampler  Source Resource
+// -------------- --------------- ----------------
+// s0             s0              t0               
+//
+//
+// Level9 shader bytecode:
+//
+    ps_2_x
+    def c0, 1, 0, 0, 0
+    dcl t0.xyz
+    dcl t1.xyz
+    dcl t2.xyz
+    dcl t3
+    dcl_2d s0
+    texld r0, t1, s0
+    texld r1, t0, s0
+    mul r1.x, r1.x, t3.x
+    mul r1.y, r0.y, t3.x
+    texld r0, t2, s0
+    mul r1.z, r0.z, t3.x
+    mov r1.w, c0.x
+    mov oC0, r1
+
+// approximately 8 instruction slots used (3 texture, 5 arithmetic)
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture2d (float,float,float,float) t0
+dcl_input_ps linear v1.xy
+dcl_input_ps linear v2.xy
+dcl_input_ps linear v3.xy
+dcl_input_ps linear v4.x
+dcl_output o0.xyzw
+dcl_temps 1
+sample r0.xyzw, v1.xyxx, t0.xyzw, s0
+mul o0.x, r0.x, v4.x
+sample r0.xyzw, v2.xyxx, t0.xyzw, s0
+mul o0.y, r0.y, v4.x
+sample r0.xyzw, v3.xyxx, t0.xyzw, s0
+mul o0.z, r0.z, v4.x
+mov o0.w, l(1.000000)
+ret 
+// Approximately 8 instruction slots used
+#endif
+
+const BYTE OculusVRDistortionPS[] =
+{
+     68,  88,  66,  67, 108, 219, 
+     61, 216,  27,   0,  27, 222, 
+    242, 132, 183,  21, 166, 141, 
+    130,  39,   1,   0,   0,   0, 
+    128,   4,   0,   0,   6,   0, 
+      0,   0,  56,   0,   0,   0, 
+     60,   1,   0,   0, 132,   2, 
+      0,   0,   0,   3,   0,   0, 
+    168,   3,   0,   0,  76,   4, 
+      0,   0,  65, 111, 110,  57, 
+    252,   0,   0,   0, 252,   0, 
+      0,   0,   0,   2, 255, 255, 
+    212,   0,   0,   0,  40,   0, 
+      0,   0,   0,   0,  40,   0, 
+      0,   0,  40,   0,   0,   0, 
+     40,   0,   1,   0,  36,   0, 
+      0,   0,  40,   0,   0,   0, 
+      0,   0,   1,   2, 255, 255, 
+     81,   0,   0,   5,   0,   0, 
+     15, 160,   0,   0, 128,  63, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+     31,   0,   0,   2,   0,   0, 
+      0, 128,   0,   0,   7, 176, 
+     31,   0,   0,   2,   0,   0, 
+      0, 128,   1,   0,   7, 176, 
+     31,   0,   0,   2,   0,   0, 
+      0, 128,   2,   0,   7, 176, 
+     31,   0,   0,   2,   0,   0, 
+      0, 128,   3,   0,  15, 176, 
+     31,   0,   0,   2,   0,   0, 
+      0, 144,   0,   8,  15, 160, 
+     66,   0,   0,   3,   0,   0, 
+     15, 128,   1,   0, 228, 176, 
+      0,   8, 228, 160,  66,   0, 
+      0,   3,   1,   0,  15, 128, 
+      0,   0, 228, 176,   0,   8, 
+    228, 160,   5,   0,   0,   3, 
+      1,   0,   1, 128,   1,   0, 
+      0, 128,   3,   0,   0, 176, 
+      5,   0,   0,   3,   1,   0, 
+      2, 128,   0,   0,  85, 128, 
+      3,   0,   0, 176,  66,   0, 
+      0,   3,   0,   0,  15, 128, 
+      2,   0, 228, 176,   0,   8, 
+    228, 160,   5,   0,   0,   3, 
+      1,   0,   4, 128,   0,   0, 
+    170, 128,   3,   0,   0, 176, 
+      1,   0,   0,   2,   1,   0, 
+      8, 128,   0,   0,   0, 160, 
+      1,   0,   0,   2,   0,   8, 
+     15, 128,   1,   0, 228, 128, 
+    255, 255,   0,   0,  83,  72, 
+     68,  82,  64,   1,   0,   0, 
+     64,   0,   0,   0,  80,   0, 
+      0,   0,  90,   0,   0,   3, 
+      0,  96,  16,   0,   0,   0, 
+      0,   0,  88,  24,   0,   4, 
+      0, 112,  16,   0,   0,   0, 
+      0,   0,  85,  85,   0,   0, 
+     98,  16,   0,   3,  50,  16, 
+     16,   0,   1,   0,   0,   0, 
+     98,  16,   0,   3,  50,  16, 
+     16,   0,   2,   0,   0,   0, 
+     98,  16,   0,   3,  50,  16, 
+     16,   0,   3,   0,   0,   0, 
+     98,  16,   0,   3,  18,  16, 
+     16,   0,   4,   0,   0,   0, 
+    101,   0,   0,   3, 242,  32, 
+     16,   0,   0,   0,   0,   0, 
+    104,   0,   0,   2,   1,   0, 
+      0,   0,  69,   0,   0,   9, 
+    242,   0,  16,   0,   0,   0, 
+      0,   0,  70,  16,  16,   0, 
+      1,   0,   0,   0,  70, 126, 
+     16,   0,   0,   0,   0,   0, 
+      0,  96,  16,   0,   0,   0, 
+      0,   0,  56,   0,   0,   7, 
+     18,  32,  16,   0,   0,   0, 
+      0,   0,  10,   0,  16,   0, 
+      0,   0,   0,   0,  10,  16, 
+     16,   0,   4,   0,   0,   0, 
+     69,   0,   0,   9, 242,   0, 
+     16,   0,   0,   0,   0,   0, 
+     70,  16,  16,   0,   2,   0, 
+      0,   0,  70, 126,  16,   0, 
+      0,   0,   0,   0,   0,  96, 
+     16,   0,   0,   0,   0,   0, 
+     56,   0,   0,   7,  34,  32, 
+     16,   0,   0,   0,   0,   0, 
+     26,   0,  16,   0,   0,   0, 
+      0,   0,  10,  16,  16,   0, 
+      4,   0,   0,   0,  69,   0, 
+      0,   9, 242,   0,  16,   0, 
+      0,   0,   0,   0,  70,  16, 
+     16,   0,   3,   0,   0,   0, 
+     70, 126,  16,   0,   0,   0, 
+      0,   0,   0,  96,  16,   0, 
+      0,   0,   0,   0,  56,   0, 
+      0,   7,  66,  32,  16,   0, 
+      0,   0,   0,   0,  42,   0, 
+     16,   0,   0,   0,   0,   0, 
+     10,  16,  16,   0,   4,   0, 
+      0,   0,  54,   0,   0,   5, 
+    130,  32,  16,   0,   0,   0, 
+      0,   0,   1,  64,   0,   0, 
+      0,   0, 128,  63,  62,   0, 
+      0,   1,  83,  84,  65,  84, 
+    116,   0,   0,   0,   8,   0, 
+      0,   0,   1,   0,   0,   0, 
+      0,   0,   0,   0,   5,   0, 
+      0,   0,   3,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   1,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      3,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   1,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+     82,  68,  69,  70, 160,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   2,   0, 
+      0,   0,  28,   0,   0,   0, 
+      0,   4, 255, 255,   0,   1, 
+      0,   0, 107,   0,   0,   0, 
+     92,   0,   0,   0,   3,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      1,   0,   0,   0,   0,   0, 
+      0,   0,  99,   0,   0,   0, 
+      2,   0,   0,   0,   5,   0, 
+      0,   0,   4,   0,   0,   0, 
+    255, 255, 255, 255,   0,   0, 
+      0,   0,   1,   0,   0,   0, 
+     13,   0,   0,   0,  76, 105, 
+    110, 101,  97, 114,   0,  84, 
+    101, 120, 116, 117, 114, 101, 
+      0,  77, 105,  99, 114, 111, 
+    115, 111, 102, 116,  32,  40, 
+     82,  41,  32,  72,  76,  83, 
+     76,  32,  83, 104,  97, 100, 
+    101, 114,  32,  67, 111, 109, 
+    112, 105, 108, 101, 114,  32, 
+     54,  46,  51,  46,  57,  54, 
+     48,  48,  46,  49,  54,  51, 
+     56,  52,   0, 171, 171, 171, 
+     73,  83,  71,  78, 156,   0, 
+      0,   0,   5,   0,   0,   0, 
+      8,   0,   0,   0, 128,   0, 
+      0,   0,   0,   0,   0,   0, 
+      1,   0,   0,   0,   3,   0, 
+      0,   0,   0,   0,   0,   0, 
+     15,   0,   0,   0, 140,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   3,   0, 
+      0,   0,   1,   0,   0,   0, 
+      7,   3,   0,   0, 140,   0, 
+      0,   0,   1,   0,   0,   0, 
+      0,   0,   0,   0,   3,   0, 
+      0,   0,   2,   0,   0,   0, 
+      7,   3,   0,   0, 140,   0, 
+      0,   0,   2,   0,   0,   0, 
+      0,   0,   0,   0,   3,   0, 
+      0,   0,   3,   0,   0,   0, 
+      7,   3,   0,   0, 149,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   3,   0, 
+      0,   0,   4,   0,   0,   0, 
+     15,   1,   0,   0,  83,  86, 
+     95,  80, 111, 115, 105, 116, 
+    105, 111, 110,   0,  84,  69, 
+     88,  67,  79,  79,  82,  68, 
+      0,  67,  79,  76,  79,  82, 
+      0, 171,  79,  83,  71,  78, 
+     44,   0,   0,   0,   1,   0, 
+      0,   0,   8,   0,   0,   0, 
+     32,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      3,   0,   0,   0,   0,   0, 
+      0,   0,  15,   0,   0,   0, 
+     83,  86,  95,  84,  97, 114, 
+    103, 101, 116,   0, 171, 171
+};
--- a/gfx/layers/d3d11/CompositorD3D11VR.hlsl
+++ b/gfx/layers/d3d11/CompositorD3D11VR.hlsl
@@ -32,23 +32,26 @@ struct VS_VR_OUTPUT {
 
 SamplerState Linear
 {
   Filter = MIN_MAG_MIP_LINEAR;
   AddressU = Clamp;
   AddressV = Clamp;
 };
 
+/*
+ * Oculus basic distortion, with chroma aberration correction
+ */
 VS_VR_OUTPUT OculusVRDistortionVS(const VS_VR_INPUT aVertex)
 {
   VS_VR_OUTPUT res;
 
-  float2 tc0 = VREyeToSource.xy * aVertex.vTexCoord0 + VREyeToSource.zw;
-  float2 tc1 = VREyeToSource.xy * aVertex.vTexCoord1 + VREyeToSource.zw;
-  float2 tc2 = VREyeToSource.xy * aVertex.vTexCoord2 + VREyeToSource.zw;
+  float2 tc0 = aVertex.vTexCoord0 * VREyeToSource.zw + VREyeToSource.xy;
+  float2 tc1 = aVertex.vTexCoord1 * VREyeToSource.zw + VREyeToSource.xy;
+  float2 tc2 = aVertex.vTexCoord2 * VREyeToSource.zw + VREyeToSource.xy;
 
   //res.vPosition.xy = aVertex.vPosition.xy;
   res.vPosition.xy = aVertex.vPosition.xy * VRDestinationScaleAndOffset.zw + VRDestinationScaleAndOffset.xy;
   res.vPosition.zw = float2(0.5, 1.0);
 
   res.vTexCoord0 = float3(tc0, 1);
   res.vTexCoord1 = float3(tc1, 1);
   res.vTexCoord2 = float3(tc2, 1);
--- a/gfx/layers/opengl/CompositorOGL.h
+++ b/gfx/layers/opengl/CompositorOGL.h
@@ -173,16 +173,17 @@ struct CompositorOGLVRObjects {
   // (in this case Oculus only).  We'll need to extend this to support
   // other device types in the future.
 
   // 0 = TEXTURE_2D, 1 = TEXTURE_RECTANGLE for source
   GLuint mDistortionProgram[2];
   GLint mUTexture[2];
   GLint mUVREyeToSource[2];
   GLint mUVRDestionatinScaleAndOffset[2];
+  GLint mUHeight[2];
 };
 
 // If you want to make this class not final, first remove calls to virtual
 // methods (Destroy) that are made in the destructor.
 class CompositorOGL final : public Compositor
 {
   typedef mozilla::gl::GLContext GLContext;
 
--- a/gfx/layers/opengl/CompositorOGLVR.cpp
+++ b/gfx/layers/opengl/CompositorOGLVR.cpp
@@ -50,33 +50,34 @@ CompositorOGL::InitializeVR()
   mVR.mATexCoord1 = 2;
   mVR.mATexCoord2 = 3;
   mVR.mAGenericAttribs = 4;
 
   ostringstream vs;
 
   vs << "uniform vec4 uVREyeToSource;\n";
   vs << "uniform vec4 uVRDestinationScaleAndOffset;\n";
+  vs << "uniform float uHeight;\n";
   vs << "attribute vec2 aPosition;\n";
   vs << "attribute vec2 aTexCoord0;\n";
   vs << "attribute vec2 aTexCoord1;\n";
   vs << "attribute vec2 aTexCoord2;\n";
   vs << "attribute vec4 aGenericAttribs;\n";
   vs << "varying vec2 vTexCoord0;\n";
   vs << "varying vec2 vTexCoord1;\n";
   vs << "varying vec2 vTexCoord2;\n";
   vs << "varying vec4 vGenericAttribs;\n";
   vs << "void main() {\n";
   vs << "  gl_Position = vec4(aPosition.xy * uVRDestinationScaleAndOffset.zw + uVRDestinationScaleAndOffset.xy, 0.5, 1.0);\n";
-  vs << "  vTexCoord0 = uVREyeToSource.xy * aTexCoord0 + uVREyeToSource.zw;\n";
-  vs << "  vTexCoord1 = uVREyeToSource.xy * aTexCoord1 + uVREyeToSource.zw;\n";
-  vs << "  vTexCoord2 = uVREyeToSource.xy * aTexCoord2 + uVREyeToSource.zw;\n";
-  vs << "  vTexCoord0.y = 1.0 - vTexCoord0.y;\n";
-  vs << "  vTexCoord1.y = 1.0 - vTexCoord1.y;\n";
-  vs << "  vTexCoord2.y = 1.0 - vTexCoord2.y;\n";
+  vs << "  vTexCoord0 = uVREyeToSource.zw * aTexCoord0 + uVREyeToSource.xy;\n";
+  vs << "  vTexCoord1 = uVREyeToSource.zw * aTexCoord1 + uVREyeToSource.xy;\n";
+  vs << "  vTexCoord2 = uVREyeToSource.zw * aTexCoord2 + uVREyeToSource.xy;\n";
+  vs << "  vTexCoord0.y = uHeight - vTexCoord0.y;\n";
+  vs << "  vTexCoord1.y = uHeight - vTexCoord1.y;\n";
+  vs << "  vTexCoord2.y = uHeight - vTexCoord2.y;\n";
   vs << "  vGenericAttribs = aGenericAttribs;\n";
   vs << "}\n";
 
   std::string vsSrcString(vs.str());
   const char *vsSrc = vsSrcString.c_str();
 
   for (int programIndex = 0; programIndex < 2; programIndex++) {
     GLenum textureTarget = programIndex == 0 ? LOCAL_GL_TEXTURE_2D : LOCAL_GL_TEXTURE_RECTANGLE;
@@ -92,17 +93,16 @@ CompositorOGL::InitializeVR()
       texture2D = "texture2DRect";
     }
 
     if (gl()->IsGLES()) {
       fs << "precision highp float;\n";
     }
 
     fs << "uniform " << sampler2D << " uTexture;\n";
-
     fs << "varying vec2 vTexCoord0;\n";
     fs << "varying vec2 vTexCoord1;\n";
     fs << "varying vec2 vTexCoord2;\n";
     fs << "varying vec4 vGenericAttribs;\n";
     fs << "void main() {\n";
     fs << "  float resR = " << texture2D << "(uTexture, vTexCoord0.xy).r;\n";
     fs << "  float resG = " << texture2D << "(uTexture, vTexCoord1.xy).g;\n";
     fs << "  float resB = " << texture2D << "(uTexture, vTexCoord2.xy).b;\n";
@@ -174,16 +174,17 @@ CompositorOGL::InitializeVR()
       gl()->fDeleteShader(shaders[1]);
 
       return false;
     }
 
     mVR.mUTexture[programIndex] = gl()->fGetUniformLocation(prog, "uTexture");
     mVR.mUVREyeToSource[programIndex] = gl()->fGetUniformLocation(prog, "uVREyeToSource");
     mVR.mUVRDestionatinScaleAndOffset[programIndex] = gl()->fGetUniformLocation(prog, "uVRDestinationScaleAndOffset");
+    mVR.mUHeight[programIndex] = gl()->fGetUniformLocation(prog, "uHeight");
 
     mVR.mDistortionProgram[programIndex] = prog;
 
     gl()->fDeleteShader(shaders[0]);
     gl()->fDeleteShader(shaders[1]);
   }
 
   mVR.mInitialized = true;
@@ -262,16 +263,20 @@ CompositorOGL::DrawVRDistortion(const gf
                  aClipRect.width, aClipRect.height);
 
   // Clear out the entire area that we want to render; this ensures that
   // the layer will be opaque, even though the mesh geometry we'll be
   // drawing below won't cover the full rectangle.
   gl()->fClearColor(0.0, 0.0, 0.0, 1.0);
   gl()->fClear(LOCAL_GL_COLOR_BUFFER_BIT | LOCAL_GL_DEPTH_BUFFER_BIT);
 
+  // Make sure that the cached current program is reset for the
+  // rest of the compositor, since we're using a custom program here
+  ResetProgram();
+
   gl()->fUseProgram(mVR.mDistortionProgram[programIndex]);
 
   gl()->fEnableVertexAttribArray(mVR.mAPosition);
   gl()->fEnableVertexAttribArray(mVR.mATexCoord0);
   gl()->fEnableVertexAttribArray(mVR.mATexCoord1);
   gl()->fEnableVertexAttribArray(mVR.mATexCoord2);
   gl()->fEnableVertexAttribArray(mVR.mAGenericAttribs);
 
@@ -288,31 +293,42 @@ CompositorOGL::DrawVRDistortion(const gf
     eyeViewport.width = size.width / 2;
     eyeViewport.height = size.height;
 
     hmdInfo->FillDistortionConstants(eye,
                                      size, eyeViewport,
                                      vpSize, aRect,
                                      shaderConstants);
 
+    float height = 1.0f;
+    float texScaleAndOffset[4] = { shaderConstants.eyeToSourceScaleAndOffset[0],
+                                   shaderConstants.eyeToSourceScaleAndOffset[1],
+                                   shaderConstants.eyeToSourceScaleAndOffset[2],
+                                   shaderConstants.eyeToSourceScaleAndOffset[3] };
+    if (textureTarget == LOCAL_GL_TEXTURE_RECTANGLE_ARB) {
+      texScaleAndOffset[0] *= size.width;
+      texScaleAndOffset[1] *= size.height;
+      texScaleAndOffset[2] *= size.width;
+      texScaleAndOffset[3] *= size.height;
+      height = size.height;
+    }
+
     gl()->fUniform4fv(mVR.mUVRDestionatinScaleAndOffset[programIndex], 1, shaderConstants.destinationScaleAndOffset);
-    gl()->fUniform4fv(mVR.mUVREyeToSource[programIndex], 1, shaderConstants.eyeToSourceScaleAndOffset);
+    gl()->fUniform4fv(mVR.mUVREyeToSource[programIndex], 1, texScaleAndOffset);
+    gl()->fUniform1f(mVR.mUHeight[programIndex], height);
 
     gl()->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, mVR.mDistortionVertices[eye]);
 
-    gl()->fVertexAttribPointer(mVR.mAPosition, 2, LOCAL_GL_FLOAT, LOCAL_GL_FALSE, sizeof(gfx::VRDistortionVertex),
-                               (void*) offsetof(gfx::VRDistortionVertex, pos));
-    gl()->fVertexAttribPointer(mVR.mATexCoord0, 2, LOCAL_GL_FLOAT, LOCAL_GL_FALSE, sizeof(gfx::VRDistortionVertex),
-                               (void*) offsetof(gfx::VRDistortionVertex, texR));
-    gl()->fVertexAttribPointer(mVR.mATexCoord1, 2, LOCAL_GL_FLOAT, LOCAL_GL_FALSE, sizeof(gfx::VRDistortionVertex),
-                               (void*) offsetof(gfx::VRDistortionVertex, texG));
-    gl()->fVertexAttribPointer(mVR.mATexCoord2, 2, LOCAL_GL_FLOAT, LOCAL_GL_FALSE, sizeof(gfx::VRDistortionVertex),
-                               (void*) offsetof(gfx::VRDistortionVertex, texB));
-    gl()->fVertexAttribPointer(mVR.mAGenericAttribs, 4, LOCAL_GL_FLOAT, LOCAL_GL_FALSE, sizeof(gfx::VRDistortionVertex),
-                               (void*) offsetof(gfx::VRDistortionVertex, genericAttribs));
+    /* This is for Oculus DistortionVertex */
+
+    gl()->fVertexAttribPointer(mVR.mAPosition,  2, LOCAL_GL_FLOAT, LOCAL_GL_FALSE, sizeof(gfx::VRDistortionVertex), (void*) (sizeof(float) * 0));
+    gl()->fVertexAttribPointer(mVR.mATexCoord0, 2, LOCAL_GL_FLOAT, LOCAL_GL_FALSE, sizeof(gfx::VRDistortionVertex), (void*) (sizeof(float) * 2));
+    gl()->fVertexAttribPointer(mVR.mATexCoord1, 2, LOCAL_GL_FLOAT, LOCAL_GL_FALSE, sizeof(gfx::VRDistortionVertex), (void*) (sizeof(float) * 4));
+    gl()->fVertexAttribPointer(mVR.mATexCoord2, 2, LOCAL_GL_FLOAT, LOCAL_GL_FALSE, sizeof(gfx::VRDistortionVertex), (void*) (sizeof(float) * 6));
+    gl()->fVertexAttribPointer(mVR.mAGenericAttribs, 4, LOCAL_GL_FLOAT, LOCAL_GL_FALSE, sizeof(gfx::VRDistortionVertex),  (void*) (sizeof(float) * 8));
 
     gl()->fBindBuffer(LOCAL_GL_ELEMENT_ARRAY_BUFFER, mVR.mDistortionIndices[eye]);
     gl()->fDrawElements(LOCAL_GL_TRIANGLES, mVR.mDistortionIndexCount[eye], LOCAL_GL_UNSIGNED_SHORT, 0);
   }
 
   // Not clear if I should disable all of this; but going to do it and hope that
   // any later code will enable what it needs.
   gl()->fDisableVertexAttribArray(mVR.mAPosition);
--- a/gfx/moz.build
+++ b/gfx/moz.build
@@ -18,16 +18,17 @@ DIRS += [
     'qcms',
     'gl',
     'layers',
     'graphite2/src',
     'harfbuzz/src',
     'ots/src',
     'thebes',
     'ipc',
+    'vr',
 ]
 
 if CONFIG['MOZ_ENABLE_SKIA']:
     DIRS += ['skia']
 
 if CONFIG['ENABLE_TESTS']:
     DIRS += ['tests/gtest']
 
--- a/gfx/thebes/gfxPlatform.cpp
+++ b/gfx/thebes/gfxPlatform.cpp
@@ -398,19 +398,18 @@ gfxPlatform::gfxPlatform()
     mSkiaGlue = nullptr;
 
     uint32_t canvasMask = BackendTypeBit(BackendType::CAIRO) | BackendTypeBit(BackendType::SKIA);
     uint32_t contentMask = BackendTypeBit(BackendType::CAIRO);
     InitBackendPrefs(canvasMask, BackendType::CAIRO,
                      contentMask, BackendType::CAIRO);
     mTotalSystemMemory = mozilla::hal::GetTotalSystemMemory();
 
-    // give ovr_Initialize a chance to be called very early on; we don't
-    // care if it succeeds or not
-    VRHMDManagerOculus::PlatformInit();
+    // give HMDs a chance to be initialized very early on
+    VRHMDManager::ManagerInit();
 }
 
 gfxPlatform*
 gfxPlatform::GetPlatform()
 {
     if (!gPlatform) {
         Init();
     }
@@ -695,17 +694,17 @@ gfxPlatform::ShutdownLayersIPC()
 }
 
 gfxPlatform::~gfxPlatform()
 {
     mScreenReferenceSurface = nullptr;
     mScreenReferenceDrawTarget = nullptr;
 
     // Clean up any VR stuff
-    VRHMDManagerOculus::Destroy();
+    VRHMDManager::ManagerDestroy();
 
     // The cairo folks think we should only clean up in debug builds,
     // but we're generally in the habit of trying to shut down as
     // cleanly as possible even in production code, so call this
     // cairo_debug_* function unconditionally.
     //
     // because cairo can assert and thus crash on shutdown, don't do this in release builds
 #if defined(DEBUG) || defined(NS_BUILD_REFCNT_LOGGING) || defined(MOZ_VALGRIND)
--- a/gfx/thebes/gfxTextRun.cpp
+++ b/gfx/thebes/gfxTextRun.cpp
@@ -924,18 +924,25 @@ gfxTextRun::BreakAndMeasureText(uint32_t
         trimmableChars = lastBreakTrimmableChars;
         trimmableAdvance = lastBreakTrimmableAdvance;
         usedHyphenation = lastBreakUsedHyphenation;
     } else {
         charsFit = aMaxLength;
     }
 
     if (aMetrics) {
-        *aMetrics = MeasureText(aStart, charsFit - trimmableChars,
+        *aMetrics = MeasureText(aStart, charsFit,
             aBoundingBoxType, aRefContext, aProvider);
+        if (trimmableChars) {
+            Metrics trimMetrics =
+                MeasureText(aStart + charsFit - trimmableChars,
+                            trimmableChars, aBoundingBoxType,
+                            aRefContext, aProvider);
+            aMetrics->mAdvanceWidth -= trimMetrics.mAdvanceWidth;
+        }
     }
     if (aTrimWhitespace) {
         *aTrimWhitespace = trimmableAdvance;
     }
     if (aUsedHyphenation) {
         *aUsedHyphenation = usedHyphenation;
     }
     if (aLastBreak && charsFit == aMaxLength) {
deleted file mode 100644
--- a/gfx/thebes/gfxVR.cpp
+++ /dev/null
@@ -1,658 +0,0 @@
-/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include <math.h>
-
-#include "prlink.h"
-#include "prmem.h"
-#include "prenv.h"
-#include "gfxPrefs.h"
-#include "gfxVR.h"
-#include "nsString.h"
-#include "mozilla/Preferences.h"
-
-#include "ovr_capi_dynamic.h"
-
-#include "nsServiceManagerUtils.h"
-#include "nsIScreenManager.h"
-
-#ifdef XP_WIN
-#include "gfxWindowsPlatform.h" // for gfxWindowsPlatform::GetDPIScale
-#endif
-
-#ifndef M_PI
-# define M_PI 3.14159265358979323846
-#endif
-
-namespace {
-
-#ifdef OVR_CAPI_LIMITED_MOZILLA
-static pfn_ovr_Initialize ovr_Initialize = nullptr;
-static pfn_ovr_Shutdown ovr_Shutdown = nullptr;
-static pfn_ovrHmd_Detect ovrHmd_Detect = nullptr;
-static pfn_ovrHmd_Create ovrHmd_Create = nullptr;
-static pfn_ovrHmd_Destroy ovrHmd_Destroy = nullptr;
-static pfn_ovrHmd_CreateDebug ovrHmd_CreateDebug = nullptr;
-static pfn_ovrHmd_GetLastError ovrHmd_GetLastError = nullptr;
-static pfn_ovrHmd_AttachToWindow ovrHmd_AttachToWindow = nullptr;
-static pfn_ovrHmd_GetEnabledCaps ovrHmd_GetEnabledCaps = nullptr;
-static pfn_ovrHmd_SetEnabledCaps ovrHmd_SetEnabledCaps = nullptr;
-static pfn_ovrHmd_ConfigureTracking ovrHmd_ConfigureTracking = nullptr;
-static pfn_ovrHmd_RecenterPose ovrHmd_RecenterPose = nullptr;
-static pfn_ovrHmd_GetTrackingState ovrHmd_GetTrackingState = nullptr;
-static pfn_ovrHmd_GetFovTextureSize ovrHmd_GetFovTextureSize = nullptr;
-static pfn_ovrHmd_GetRenderDesc ovrHmd_GetRenderDesc = nullptr;
-static pfn_ovrHmd_CreateDistortionMesh ovrHmd_CreateDistortionMesh = nullptr;
-static pfn_ovrHmd_DestroyDistortionMesh ovrHmd_DestroyDistortionMesh = nullptr;
-static pfn_ovrHmd_GetRenderScaleAndOffset ovrHmd_GetRenderScaleAndOffset = nullptr;
-static pfn_ovrHmd_GetFrameTiming ovrHmd_GetFrameTiming = nullptr;
-static pfn_ovrHmd_BeginFrameTiming ovrHmd_BeginFrameTiming = nullptr;
-static pfn_ovrHmd_EndFrameTiming ovrHmd_EndFrameTiming = nullptr;
-static pfn_ovrHmd_ResetFrameTiming ovrHmd_ResetFrameTiming = nullptr;
-static pfn_ovrHmd_GetEyePoses ovrHmd_GetEyePoses = nullptr;
-static pfn_ovrHmd_GetHmdPosePerEye ovrHmd_GetHmdPosePerEye = nullptr;
-static pfn_ovrHmd_GetEyeTimewarpMatrices ovrHmd_GetEyeTimewarpMatrices = nullptr;
-static pfn_ovrMatrix4f_Projection ovrMatrix4f_Projection = nullptr;
-static pfn_ovrMatrix4f_OrthoSubProjection ovrMatrix4f_OrthoSubProjection = nullptr;
-static pfn_ovr_GetTimeInSeconds ovr_GetTimeInSeconds = nullptr;
-
-#if defined(XP_WIN)
-# ifdef HAVE_64BIT_BUILD
-#  define OVR_LIB_NAME "libovr64.dll"
-# else
-#  define OVR_LIB_NAME "libovr.dll"
-# endif
-#elif defined(XP_MACOSX)
-# define OVR_LIB_NAME "libovr.dylib"
-#else
-# define OVR_LIB_NAME 0
-#endif
-
-static bool
-InitializeOculusCAPI()
-{
-  static PRLibrary *ovrlib = nullptr;
-
-  if (!ovrlib) {
-    const char *libName = OVR_LIB_NAME;
-
-    // If the pref is present, we override libName
-    nsAdoptingCString prefLibName = mozilla::Preferences::GetCString("dom.vr.ovr_lib_path");
-    if (prefLibName && prefLibName.get()) {
-      libName = prefLibName.get();
-    }
-
-    // If the env var is present, we override libName
-    if (PR_GetEnv("OVR_LIB_NAME")) {
-      libName = PR_GetEnv("OVR_LIB_NAME");
-    }
-
-    if (!libName) {
-      printf_stderr("Don't know how to find Oculus VR library; missing dom.vr.ovr_lib_path or OVR_LIB_NAME\n");
-      return false;
-    }
-
-    ovrlib = PR_LoadLibrary(libName);
-
-    if (!ovrlib) {
-      // Not found? Try harder. Needed mainly on OSX/etc. where
-      // the binary location is not in the search path.
-      const char *xulName = "libxul.so";
-#if defined(XP_MACOSX)
-      xulName = "XUL";
-#endif
-
-      char *xulpath = PR_GetLibraryFilePathname(xulName, (PRFuncPtr) &InitializeOculusCAPI);
-      if (xulpath) {
-        char *xuldir = strrchr(xulpath, '/');
-        if (xuldir) {
-          *xuldir = 0;
-          xuldir = xulpath;
-
-          char *ovrpath = PR_GetLibraryName(xuldir, libName);
-          ovrlib = PR_LoadLibrary(ovrpath);
-          PR_Free(ovrpath);
-        }
-        PR_Free(xulpath);
-      }
-    }
-
-    if (!ovrlib) {
-      printf_stderr("Failed to load Oculus VR library, tried '%s'\n", libName);
-      return false;
-    }
-  }
-
-  // was it already initialized?
-  if (ovr_Initialize)
-    return true;
-
-#define REQUIRE_FUNCTION(_x) do { \
-    *(void **)&_x = (void *) PR_FindSymbol(ovrlib, #_x);                \
-    if (!_x) { printf_stderr(#_x " symbol missing\n"); goto fail; }       \
-  } while (0)
-
-  REQUIRE_FUNCTION(ovr_Initialize);
-  REQUIRE_FUNCTION(ovr_Shutdown);
-  REQUIRE_FUNCTION(ovrHmd_Detect);
-  REQUIRE_FUNCTION(ovrHmd_Create);
-  REQUIRE_FUNCTION(ovrHmd_Destroy);
-  REQUIRE_FUNCTION(ovrHmd_CreateDebug);
-  REQUIRE_FUNCTION(ovrHmd_GetLastError);
-  REQUIRE_FUNCTION(ovrHmd_AttachToWindow);
-  REQUIRE_FUNCTION(ovrHmd_GetEnabledCaps);
-  REQUIRE_FUNCTION(ovrHmd_SetEnabledCaps);
-  REQUIRE_FUNCTION(ovrHmd_ConfigureTracking);
-  REQUIRE_FUNCTION(ovrHmd_RecenterPose);
-  REQUIRE_FUNCTION(ovrHmd_GetTrackingState);
-
-  REQUIRE_FUNCTION(ovrHmd_GetFovTextureSize);
-  REQUIRE_FUNCTION(ovrHmd_GetRenderDesc);
-  REQUIRE_FUNCTION(ovrHmd_CreateDistortionMesh);
-  REQUIRE_FUNCTION(ovrHmd_DestroyDistortionMesh);
-  REQUIRE_FUNCTION(ovrHmd_GetRenderScaleAndOffset);
-  REQUIRE_FUNCTION(ovrHmd_GetFrameTiming);
-  REQUIRE_FUNCTION(ovrHmd_BeginFrameTiming);
-  REQUIRE_FUNCTION(ovrHmd_EndFrameTiming);
-  REQUIRE_FUNCTION(ovrHmd_ResetFrameTiming);
-  REQUIRE_FUNCTION(ovrHmd_GetEyePoses);
-  REQUIRE_FUNCTION(ovrHmd_GetHmdPosePerEye);
-  REQUIRE_FUNCTION(ovrHmd_GetEyeTimewarpMatrices);
-  REQUIRE_FUNCTION(ovrMatrix4f_Projection);
-  REQUIRE_FUNCTION(ovrMatrix4f_OrthoSubProjection);
-  REQUIRE_FUNCTION(ovr_GetTimeInSeconds);
-
-#undef REQUIRE_FUNCTION
-
-  return true;
-
- fail:
-  ovr_Initialize = nullptr;
-  return false;
-}
-
-#else
-// we're statically linked; it's available
-static bool InitializeOculusCAPI()
-{
-  return true;
-}
-#endif
-
-} // anonymous namespace
-
-using namespace mozilla::gfx;
-
-// Dummy nsIScreen implementation, for when we just need to specify a size
-class FakeScreen : public nsIScreen
-{
-public:
-  explicit FakeScreen(const IntRect& aScreenRect)
-    : mScreenRect(aScreenRect)
-  { }
-
-  NS_DECL_ISUPPORTS
-
-  NS_IMETHOD GetRect(int32_t *l, int32_t *t, int32_t *w, int32_t *h) override {
-    *l = mScreenRect.x;
-    *t = mScreenRect.y;
-    *w = mScreenRect.width;
-    *h = mScreenRect.height;
-    return NS_OK;
-  }
-  NS_IMETHOD GetAvailRect(int32_t *l, int32_t *t, int32_t *w, int32_t *h) override {
-    return GetRect(l, t, w, h);
-  }
-  NS_IMETHOD GetRectDisplayPix(int32_t *l, int32_t *t, int32_t *w, int32_t *h) override {
-    return GetRect(l, t, w, h);
-  }
-  NS_IMETHOD GetAvailRectDisplayPix(int32_t *l, int32_t *t, int32_t *w, int32_t *h) override {
-    return GetAvailRect(l, t, w, h);
-  }
-
-  NS_IMETHOD GetId(uint32_t* aId) override { *aId = (uint32_t)-1; return NS_OK; }
-  NS_IMETHOD GetPixelDepth(int32_t* aPixelDepth) override { *aPixelDepth = 24; return NS_OK; }
-  NS_IMETHOD GetColorDepth(int32_t* aColorDepth) override { *aColorDepth = 24; return NS_OK; }
-
-  NS_IMETHOD LockMinimumBrightness(uint32_t aBrightness) override { return NS_ERROR_NOT_AVAILABLE; }
-  NS_IMETHOD UnlockMinimumBrightness(uint32_t aBrightness) override { return NS_ERROR_NOT_AVAILABLE; }
-  NS_IMETHOD GetRotation(uint32_t* aRotation) override {
-    *aRotation = nsIScreen::ROTATION_0_DEG;
-    return NS_OK;
-  }
-  NS_IMETHOD SetRotation(uint32_t aRotation) override { return NS_ERROR_NOT_AVAILABLE; }
-  NS_IMETHOD GetContentsScaleFactor(double* aContentsScaleFactor) override {
-    *aContentsScaleFactor = 1.0;
-    return NS_OK;
-  }
-
-protected:
-  virtual ~FakeScreen() {}
-
-  IntRect mScreenRect;
-};
-
-NS_IMPL_ISUPPORTS(FakeScreen, nsIScreen)
-
-class HMDInfoOculus : public VRHMDInfo {
-  friend class VRHMDManagerOculusImpl;
-public:
-  explicit HMDInfoOculus(ovrHmd aHMD);
-
-  bool SetFOV(const VRFieldOfView& aFOVLeft, const VRFieldOfView& aFOVRight,
-              double zNear, double zFar) override;
-
-  bool StartSensorTracking() override;
-  VRHMDSensorState GetSensorState(double timeOffset) override;
-  void StopSensorTracking() override;
-  void ZeroSensor() override;
-
-  void FillDistortionConstants(uint32_t whichEye,
-                               const IntSize& textureSize, const IntRect& eyeViewport,
-                               const Size& destViewport, const Rect& destRect,
-                               VRDistortionConstants& values) override;
-
-  void Destroy();
-
-protected:
-  virtual ~HMDInfoOculus() {
-      Destroy();
-      MOZ_COUNT_DTOR_INHERITED(HMDInfoOculus, VRHMDInfo);
-  }
-
-  ovrHmd mHMD;
-  ovrFovPort mFOVPort[2];
-  uint32_t mStartCount;
-};
-
-static ovrFovPort
-ToFovPort(const VRFieldOfView& aFOV)
-{
-  ovrFovPort fovPort;
-  fovPort.LeftTan = tan(aFOV.leftDegrees * M_PI / 180.0);
-  fovPort.RightTan = tan(aFOV.rightDegrees * M_PI / 180.0);
-  fovPort.UpTan = tan(aFOV.upDegrees * M_PI / 180.0);
-  fovPort.DownTan = tan(aFOV.downDegrees * M_PI / 180.0);
-  return fovPort;
-}
-
-static VRFieldOfView
-FromFovPort(const ovrFovPort& aFOV)
-{
-  VRFieldOfView fovInfo;
-  fovInfo.leftDegrees = atan(aFOV.LeftTan) * 180.0 / M_PI;
-  fovInfo.rightDegrees = atan(aFOV.RightTan) * 180.0 / M_PI;
-  fovInfo.upDegrees = atan(aFOV.UpTan) * 180.0 / M_PI;
-  fovInfo.downDegrees = atan(aFOV.DownTan) * 180.0 / M_PI;
-  return fovInfo;
-}
-
-HMDInfoOculus::HMDInfoOculus(ovrHmd aHMD)
-  : VRHMDInfo(VRHMDType::Oculus)
-  , mHMD(aHMD)
-  , mStartCount(0)
-{
-  MOZ_COUNT_CTOR_INHERITED(HMDInfoOculus, VRHMDInfo);
-
-  mSupportedSensorBits = 0;
-  if (mHMD->TrackingCaps & ovrTrackingCap_Orientation)
-    mSupportedSensorBits |= State_Orientation;
-  if (mHMD->TrackingCaps & ovrTrackingCap_Position)
-    mSupportedSensorBits |= State_Position;
-
-  mRecommendedEyeFOV[Eye_Left] = FromFovPort(mHMD->DefaultEyeFov[ovrEye_Left]);
-  mRecommendedEyeFOV[Eye_Right] = FromFovPort(mHMD->DefaultEyeFov[ovrEye_Right]);
-
-  mMaximumEyeFOV[Eye_Left] = FromFovPort(mHMD->MaxEyeFov[ovrEye_Left]);
-  mMaximumEyeFOV[Eye_Right] = FromFovPort(mHMD->MaxEyeFov[ovrEye_Right]);
-
-  SetFOV(mRecommendedEyeFOV[Eye_Left], mRecommendedEyeFOV[Eye_Right], 0.01, 10000.0);
-
-  nsCOMPtr<nsIScreenManager> screenmgr = do_GetService("@mozilla.org/gfx/screenmanager;1");
-  if (screenmgr) {
-    screenmgr->ScreenForRect(mHMD->WindowsPos.x, mHMD->WindowsPos.y,
-                             mHMD->Resolution.w, mHMD->Resolution.h,
-                             getter_AddRefs(mScreen));
-  }
-}
-
-void
-HMDInfoOculus::Destroy()
-{
-  if (mHMD) {
-    ovrHmd_Destroy(mHMD);
-    mHMD = nullptr;
-  }
-}
-
-bool
-HMDInfoOculus::SetFOV(const VRFieldOfView& aFOVLeft, const VRFieldOfView& aFOVRight,
-                      double zNear, double zFar)
-{
-  float pixelsPerDisplayPixel = 1.0;
-  ovrSizei texSize[2];
-
-  uint32_t caps = ovrDistortionCap_Chromatic | ovrDistortionCap_Vignette; // XXX TODO add TimeWarp
-
-  // get eye parameters and create the mesh
-  for (uint32_t eye = 0; eye < NumEyes; eye++) {
-    mEyeFOV[eye] = eye == 0 ? aFOVLeft : aFOVRight;
-    mFOVPort[eye] = ToFovPort(mEyeFOV[eye]);
-
-    ovrEyeRenderDesc renderDesc = ovrHmd_GetRenderDesc(mHMD, (ovrEyeType) eye, mFOVPort[eye]);
-
-    // these values are negated so that content can add the adjustment to its camera position,
-    // instead of subtracting
-    mEyeTranslation[eye] = Point3D(-renderDesc.ViewAdjust.x, -renderDesc.ViewAdjust.y, -renderDesc.ViewAdjust.z);
-
-    // note that we are using a right-handed coordinate system here, to match CSS
-    ovrMatrix4f projMatrix = ovrMatrix4f_Projection(mFOVPort[eye], zNear, zFar, true);
-
-    // XXX this is gross, we really need better methods on Matrix4x4
-    memcpy(&mEyeProjectionMatrix[eye], projMatrix.M, sizeof(ovrMatrix4f));
-    mEyeProjectionMatrix[eye].Transpose();
-
-    texSize[eye] = ovrHmd_GetFovTextureSize(mHMD, (ovrEyeType) eye, mFOVPort[eye], pixelsPerDisplayPixel);
-
-    ovrDistortionMesh mesh;
-    bool ok = ovrHmd_CreateDistortionMesh(mHMD, (ovrEyeType) eye, mFOVPort[eye], caps, &mesh);
-    if (!ok)
-      return false;
-
-    mDistortionMesh[eye].mVertices.SetLength(mesh.VertexCount);
-    mDistortionMesh[eye].mIndices.SetLength(mesh.IndexCount);
-
-    ovrDistortionVertex *srcv = mesh.pVertexData;
-    VRDistortionVertex *destv = mDistortionMesh[eye].mVertices.Elements();
-    memset(destv, 0, mesh.VertexCount * sizeof(VRDistortionVertex));
-    for (uint32_t i = 0; i < mesh.VertexCount; ++i) {
-      destv[i].pos[0] = srcv[i].ScreenPosNDC.x;
-      destv[i].pos[1] = srcv[i].ScreenPosNDC.y;
-
-      destv[i].texR[0] = srcv[i].TanEyeAnglesR.x;
-      destv[i].texR[1] = srcv[i].TanEyeAnglesR.y;
-      destv[i].texG[0] = srcv[i].TanEyeAnglesG.x;
-      destv[i].texG[1] = srcv[i].TanEyeAnglesG.y;
-      destv[i].texB[0] = srcv[i].TanEyeAnglesB.x;
-      destv[i].texB[1] = srcv[i].TanEyeAnglesB.y;
-
-      destv[i].genericAttribs[0] = srcv[i].VignetteFactor;
-      destv[i].genericAttribs[1] = srcv[i].TimeWarpFactor;
-    }
-
-    memcpy(mDistortionMesh[eye].mIndices.Elements(), mesh.pIndexData, mesh.IndexCount * sizeof(uint16_t));
-    ovrHmd_DestroyDistortionMesh(&mesh);
-  }
-
-  // take the max of both for eye resolution
-  mEyeResolution.width = std::max(texSize[Eye_Left].w, texSize[Eye_Right].w);
-  mEyeResolution.height = std::max(texSize[Eye_Left].h, texSize[Eye_Right].h);
-
-  mConfiguration.hmdType = mType;
-  mConfiguration.value = 0;
-  mConfiguration.fov[0] = aFOVLeft;
-  mConfiguration.fov[1] = aFOVRight;
-
-  return true;
-  //* need to call this during rendering each frame I think? */
-  //ovrHmd_GetRenderScaleAndOffset(fovPort, texSize, renderViewport, uvScaleOffsetOut);
-}
-
-void
-HMDInfoOculus::FillDistortionConstants(uint32_t whichEye,
-                                       const IntSize& textureSize,
-                                       const IntRect& eyeViewport,
-                                       const Size& destViewport,
-                                       const Rect& destRect,
-                                       VRDistortionConstants& values)
-{
-  ovrSizei texSize = { textureSize.width, textureSize.height };
-  ovrRecti eyePort = { { eyeViewport.x, eyeViewport.y }, { eyeViewport.width, eyeViewport.height } };
-  ovrVector2f scaleOut[2];
-
-  ovrHmd_GetRenderScaleAndOffset(mFOVPort[whichEye], texSize, eyePort, scaleOut);
-
-  values.eyeToSourceScaleAndOffset[0] = scaleOut[0].x;
-  values.eyeToSourceScaleAndOffset[1] = scaleOut[0].y;
-  values.eyeToSourceScaleAndOffset[2] = scaleOut[1].x;
-  values.eyeToSourceScaleAndOffset[3] = scaleOut[1].y;
-
-  // These values are in clip space [-1..1] range, but we're providing
-  // scaling in the 0..2 space for sanity.
-
-  // this is the destRect in clip space
-  float x0 = destRect.x / destViewport.width * 2.0 - 1.0;
-  float x1 = (destRect.x + destRect.width) / destViewport.width * 2.0 - 1.0;
-
-  float y0 = destRect.y / destViewport.height * 2.0 - 1.0;
-  float y1 = (destRect.y + destRect.height) / destViewport.height * 2.0 - 1.0;
-
-  // offset
-  values.destinationScaleAndOffset[0] = (x0+x1) / 2.0;
-  values.destinationScaleAndOffset[1] = (y0+y1) / 2.0;
-  // scale
-  values.destinationScaleAndOffset[2] = destRect.width / destViewport.width;
-  values.destinationScaleAndOffset[3] = destRect.height / destViewport.height;
-}
-
-bool
-HMDInfoOculus::StartSensorTracking()
-{
-  if (mStartCount == 0) {
-    bool ok = ovrHmd_ConfigureTracking(mHMD, ovrTrackingCap_Orientation | ovrTrackingCap_Position, 0);
-    if (!ok)
-      return false;
-  }
-
-  mStartCount++;
-  return true;
-}
-
-void
-HMDInfoOculus::StopSensorTracking()
-{
-  if (--mStartCount == 0) {
-    ovrHmd_ConfigureTracking(mHMD, 0, 0);
-  }
-}
-
-void
-HMDInfoOculus::ZeroSensor()
-{
-  ovrHmd_RecenterPose(mHMD);
-}
-
-VRHMDSensorState
-HMDInfoOculus::GetSensorState(double timeOffset)
-{
-  VRHMDSensorState result;
-  result.Clear();
-
-  // XXX this is the wrong time base for timeOffset; we need to figure out how to synchronize
-  // the Oculus time base and the browser one.
-  ovrTrackingState state = ovrHmd_GetTrackingState(mHMD, ovr_GetTimeInSeconds() + timeOffset);
-  ovrPoseStatef& pose(state.HeadPose);
-
-  result.timestamp = pose.TimeInSeconds;
-
-  if (state.StatusFlags & ovrStatus_OrientationTracked) {
-    result.flags |= State_Orientation;
-
-    result.orientation[0] = pose.ThePose.Orientation.x;
-    result.orientation[1] = pose.ThePose.Orientation.y;
-    result.orientation[2] = pose.ThePose.Orientation.z;
-    result.orientation[3] = pose.ThePose.Orientation.w;
-    
-    result.angularVelocity[0] = pose.AngularVelocity.x;
-    result.angularVelocity[1] = pose.AngularVelocity.y;
-    result.angularVelocity[2] = pose.AngularVelocity.z;
-
-    result.angularAcceleration[0] = pose.AngularAcceleration.x;
-    result.angularAcceleration[1] = pose.AngularAcceleration.y;
-    result.angularAcceleration[2] = pose.AngularAcceleration.z;
-  }
-
-  if (state.StatusFlags & ovrStatus_PositionTracked) {
-    result.flags |= State_Position;
-
-    result.position[0] = pose.ThePose.Position.x;
-    result.position[1] = pose.ThePose.Position.y;
-    result.position[2] = pose.ThePose.Position.z;
-    
-    result.linearVelocity[0] = pose.LinearVelocity.x;
-    result.linearVelocity[1] = pose.LinearVelocity.y;
-    result.linearVelocity[2] = pose.LinearVelocity.z;
-
-    result.linearAcceleration[0] = pose.LinearAcceleration.x;
-    result.linearAcceleration[1] = pose.LinearAcceleration.y;
-    result.linearAcceleration[2] = pose.LinearAcceleration.z;
-  }
-
-  return result;
-}
-
-namespace mozilla {
-namespace gfx {
-
-class VRHMDManagerOculusImpl {
-public:
-  VRHMDManagerOculusImpl() : mOculusInitialized(false), mOculusPlatformInitialized(false)
-  { }
-
-  bool PlatformInit();
-  bool Init();
-  void Destroy();
-  void GetOculusHMDs(nsTArray<nsRefPtr<VRHMDInfo> >& aHMDResult);
-protected:
-  nsTArray<nsRefPtr<HMDInfoOculus>> mOculusHMDs;
-  bool mOculusInitialized;
-  bool mOculusPlatformInitialized;
-};
-
-} // namespace gfx
-} // namespace mozilla
-
-VRHMDManagerOculusImpl *VRHMDManagerOculus::mImpl = nullptr;
-
-// These just forward to the Impl class, to have a non-static container for various
-// objects.
-
-bool
-VRHMDManagerOculus::PlatformInit()
-{
-  if (!mImpl) {
-    mImpl = new VRHMDManagerOculusImpl;
-  }
-  return mImpl->PlatformInit();
-}
-
-bool
-VRHMDManagerOculus::Init()
-{
-  if (!mImpl) {
-    mImpl = new VRHMDManagerOculusImpl;
-  }
-  return mImpl->Init();
-}
-
-void
-VRHMDManagerOculus::GetOculusHMDs(nsTArray<nsRefPtr<VRHMDInfo>>& aHMDResult)
-{
-  if (!mImpl) {
-    mImpl = new VRHMDManagerOculusImpl;
-  }
-  mImpl->GetOculusHMDs(aHMDResult);
-}
-
-void
-VRHMDManagerOculus::Destroy()
-{
-  if (!mImpl)
-    return;
-  mImpl->Destroy();
-  delete mImpl;
-  mImpl = nullptr;
-}
-
-bool
-VRHMDManagerOculusImpl::PlatformInit()
-{
-  if (mOculusPlatformInitialized)
-    return true;
-
-  if (!gfxPrefs::VREnabled())
-    return false;
-
-  if (!InitializeOculusCAPI())
-    return false;
-
-  bool ok = ovr_Initialize();
-
-  if (!ok)
-    return false;
-
-  mOculusPlatformInitialized = true;
-  return true;
-}
-
-bool
-VRHMDManagerOculusImpl::Init()
-{
-  if (mOculusInitialized)
-    return true;
-
-  if (!PlatformInit())
-    return false;
-
-  int count = ovrHmd_Detect();
-
-  for (int i = 0; i < count; ++i) {
-    ovrHmd hmd = ovrHmd_Create(i);
-    if (!hmd)
-      continue;
-    nsRefPtr<HMDInfoOculus> oc = new HMDInfoOculus(hmd);
-    mOculusHMDs.AppendElement(oc);
-  }
-
-  // VRAddTestDevices == 1: add test device only if no real devices present
-  // VRAddTestDevices == 2: add test device always
-  if ((count == 0 && gfxPrefs::VRAddTestDevices() == 1) ||
-      (gfxPrefs::VRAddTestDevices() == 2))
-  {
-    ovrHmd hmd = ovrHmd_CreateDebug(ovrHmd_DK2);
-    if (hmd) {
-      nsRefPtr<HMDInfoOculus> oc = new HMDInfoOculus(hmd);
-      mOculusHMDs.AppendElement(oc);
-    }
-  }
-
-  mOculusInitialized = true;
-  return true;
-}
-
-void
-VRHMDManagerOculusImpl::Destroy()
-{
-  if (!mOculusInitialized)
-    return;
-
-  for (size_t i = 0; i < mOculusHMDs.Length(); ++i) {
-    mOculusHMDs[i]->Destroy();
-  }
-
-  mOculusHMDs.Clear();
-
-  ovr_Shutdown();
-  mOculusInitialized = false;
-}
-
-void
-VRHMDManagerOculusImpl::GetOculusHMDs(nsTArray<nsRefPtr<VRHMDInfo>>& aHMDResult)
-{
-  Init();
-  for (size_t i = 0; i < mOculusHMDs.Length(); ++i) {
-    aHMDResult.AppendElement(mOculusHMDs[i]);
-  }
-}
deleted file mode 100644
--- a/gfx/thebes/gfxVR.h
+++ /dev/null
@@ -1,217 +0,0 @@
-/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef GFX_VR_H
-#define GFX_VR_H
-
-#include "nsTArray.h"
-#include "nsIScreen.h"
-#include "nsCOMPtr.h"
-#include "nsRefPtr.h"
-
-#include "mozilla/gfx/2D.h"
-#include "mozilla/EnumeratedArray.h"
-
-namespace mozilla {
-namespace gfx {
-
-enum class VRHMDType : uint16_t {
-  Oculus,
-  NumHMDTypes
-};
-
-struct VRFieldOfView {
-  static VRFieldOfView FromCSSPerspectiveInfo(double aPerspectiveDistance,
-                                              const Point& aPerspectiveOrigin,
-                                              const Point& aTransformOrigin,
-                                              const Rect& aContentRectangle)
-  {
-    /**/
-    return VRFieldOfView();
-  }
-
-  VRFieldOfView() {}
-  VRFieldOfView(double up, double right, double down, double left)
-    : upDegrees(up), rightDegrees(right), downDegrees(down), leftDegrees(left)
-  {}
-
-  bool operator==(const VRFieldOfView& other) const {
-    return other.upDegrees == upDegrees &&
-           other.downDegrees == downDegrees &&
-           other.rightDegrees == rightDegrees &&
-           other.leftDegrees == leftDegrees;
-  }
-
-  bool operator!=(const VRFieldOfView& other) const {
-    return !(*this == other);
-  }
-
-  bool IsZero() const {
-    return upDegrees == 0.0 ||
-      rightDegrees == 0.0 ||
-      downDegrees == 0.0 ||
-      leftDegrees == 0.0;
-  }
-
-  double upDegrees;
-  double rightDegrees;
-  double downDegrees;
-  double leftDegrees;
-};
-
-// 12 floats per vertex. Position, tex coordinates
-// for each channel, and 4 generic attributes
-struct VRDistortionConstants {
-  float eyeToSourceScaleAndOffset[4];
-  float destinationScaleAndOffset[4];
-};
-
-struct VRDistortionVertex {
-  float pos[2];
-  float texR[2];
-  float texG[2];
-  float texB[2];
-  float genericAttribs[4];
-};
-
-struct VRDistortionMesh {
-  nsTArray<VRDistortionVertex> mVertices;
-  nsTArray<uint16_t> mIndices;
-};
-
-struct VRHMDSensorState {
-  double timestamp;
-  uint32_t flags;
-  float orientation[4];
-  float position[3];
-  float angularVelocity[3];
-  float angularAcceleration[3];
-  float linearVelocity[3];
-  float linearAcceleration[3];
-
-  void Clear() {
-    memset(this, 0, sizeof(VRHMDSensorState));
-  }
-};
-
-/* A pure data struct that can be used to see if
- * the configuration of one HMDInfo matches another; for rendering purposes,
- * really asking "can the rendering details of this one be used for the other"
- */
-struct VRHMDConfiguration {
-  VRHMDConfiguration() : hmdType(VRHMDType::NumHMDTypes) {}
-
-  bool operator==(const VRHMDConfiguration& other) const {
-    return hmdType == other.hmdType &&
-      value == other.value &&
-      fov[0] == other.fov[0] &&
-      fov[1] == other.fov[1];
-  }
-
-  bool operator!=(const VRHMDConfiguration& other) const {
-    return hmdType != other.hmdType ||
-      value != other.value ||
-      fov[0] != other.fov[0] ||
-      fov[1] != other.fov[1];
-  }
-
-  bool IsValid() const {
-    return hmdType != VRHMDType::NumHMDTypes;
-  }
-
-  VRHMDType hmdType;
-  uint32_t value;
-  VRFieldOfView fov[2];
-};
-
-class VRHMDInfo {
-public:
-  enum Eye {
-    Eye_Left,
-    Eye_Right,
-    NumEyes
-  };
-
-  enum StateValidFlags {
-    State_Position = 1 << 1,
-    State_Orientation = 1 << 2
-  };
-
-public:
-  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VRHMDInfo)
-
-  VRHMDType GetType() const { return mType; }
-
-  virtual const VRFieldOfView& GetRecommendedEyeFOV(uint32_t whichEye) { return mRecommendedEyeFOV[whichEye]; }
-  virtual const VRFieldOfView& GetMaximumEyeFOV(uint32_t whichEye) { return mMaximumEyeFOV[whichEye]; }
-
-  const VRHMDConfiguration& GetConfiguration() const { return mConfiguration; }
-
-  /* set the FOV for this HMD unit; this triggers a computation of all the remaining bits.  Returns false if it fails */
-  virtual bool SetFOV(const VRFieldOfView& aFOVLeft, const VRFieldOfView& aFOVRight,
-                      double zNear, double zFar) = 0;
-  const VRFieldOfView& GetEyeFOV(uint32_t whichEye)  { return mEyeFOV[whichEye]; }
-
-  /* Suggested resolution for rendering a single eye.
-   * Assumption is that left/right rendering will be 2x of this size.
-   * XXX fix this for vertical displays
-   */
-  const IntSize& SuggestedEyeResolution() const { return mEyeResolution; }
-  const Point3D& GetEyeTranslation(uint32_t whichEye) const { return mEyeTranslation[whichEye]; }
-  const Matrix4x4& GetEyeProjectionMatrix(uint32_t whichEye) const { return mEyeProjectionMatrix[whichEye]; }
-
-  virtual uint32_t GetSupportedSensorStateBits() { return mSupportedSensorBits; }
-  virtual bool StartSensorTracking() = 0;
-  virtual VRHMDSensorState GetSensorState(double timeOffset = 0.0) = 0;
-  virtual void StopSensorTracking() = 0;
-
-  virtual void ZeroSensor() = 0;
-
-  virtual void FillDistortionConstants(uint32_t whichEye,
-                                       const IntSize& textureSize, // the full size of the texture
-                                       const IntRect& eyeViewport, // the viewport within the texture for the current eye
-                                       const Size& destViewport,   // the size of the destination viewport
-                                       const Rect& destRect,       // the rectangle within the dest viewport that this should be rendered
-                                       VRDistortionConstants& values) = 0;
-
-  virtual const VRDistortionMesh& GetDistortionMesh(uint32_t whichEye) const { return mDistortionMesh[whichEye]; }
-
-  // The nsIScreen that represents this device
-  virtual nsIScreen* GetScreen() { return mScreen; }
-
-protected:
-  explicit VRHMDInfo(VRHMDType aType) : mType(aType) { MOZ_COUNT_CTOR(VRHMDInfo); }
-  virtual ~VRHMDInfo() { MOZ_COUNT_DTOR(VRHMDInfo); }
-
-  VRHMDType mType;
-  VRHMDConfiguration mConfiguration;
-
-  VRFieldOfView mEyeFOV[NumEyes];
-  IntSize mEyeResolution;
-  Point3D mEyeTranslation[NumEyes];
-  Matrix4x4 mEyeProjectionMatrix[NumEyes];
-  VRDistortionMesh mDistortionMesh[NumEyes];
-  uint32_t mSupportedSensorBits;
-
-  VRFieldOfView mRecommendedEyeFOV[NumEyes];
-  VRFieldOfView mMaximumEyeFOV[NumEyes];
-
-  nsCOMPtr<nsIScreen> mScreen;
-};
-
-class VRHMDManagerOculusImpl;
-class VRHMDManagerOculus {
-  static VRHMDManagerOculusImpl *mImpl;
-public:
-  static bool PlatformInit();
-  static bool Init();
-  static void Destroy();
-  static void GetOculusHMDs(nsTArray<nsRefPtr<VRHMDInfo> >& aHMDResult);
-};
-
-} // namespace gfx
-} // namespace mozilla
-
-#endif /* GFX_VR_H */
--- a/gfx/thebes/gfxWindowsPlatform.cpp
+++ b/gfx/thebes/gfxWindowsPlatform.cpp
@@ -1870,17 +1870,16 @@ gfxWindowsPlatform::InitD3D11Devices()
   // to fallback to D3D9 or Basic layers. If WARP is not disabled it will use
   // a WARP device which should always be available on Windows 7 and higher.
 
   mD3D11DeviceInitialized = true;
 
   MOZ_ASSERT(!mD3D11Device);
 
   bool useWARP = false;
-  ScopedGfxFeatureReporter reporterWARP("D3D11-WARP", gfxPrefs::LayersD3D11ForceWARP());
 
   nsCOMPtr<nsIGfxInfo> gfxInfo = do_GetService("@mozilla.org/gfx/info;1");
   if (gfxInfo) {
     int32_t status;
     if (NS_SUCCEEDED(gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_DIRECT3D_11_LAYERS, &status))) {
       if (status != nsIGfxInfo::FEATURE_STATUS_OK) {
 
         if (gfxPrefs::LayersD3D11DisableWARP()) {
@@ -1957,16 +1956,17 @@ gfxWindowsPlatform::InitD3D11Devices()
     }
   }
 
   if (useWARP) {
     MOZ_ASSERT(!gfxPrefs::LayersD3D11DisableWARP());
     MOZ_ASSERT(!mD3D11Device);
     MOZ_ASSERT(!adapter);
 
+    ScopedGfxFeatureReporter reporterWARP("D3D11-WARP", gfxPrefs::LayersD3D11ForceWARP());
     hr = d3d11CreateDevice(nullptr, D3D_DRIVER_TYPE_WARP, nullptr,
                            // Use
                            // D3D11_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS
                            // to prevent bug 1092260. IE 11 also uses this flag.
                            D3D11_CREATE_DEVICE_BGRA_SUPPORT,
                            featureLevels.Elements(), featureLevels.Length(),
                            D3D11_SDK_VERSION, byRef(mD3D11Device), nullptr, nullptr);
 
--- a/gfx/thebes/moz.build
+++ b/gfx/thebes/moz.build
@@ -44,17 +44,16 @@ EXPORTS += [
     'gfxSharedQuartzSurface.h',
     'gfxSkipChars.h',
     'gfxSVGGlyphs.h',
     'gfxTeeSurface.h',
     'gfxTextRun.h',
     'gfxTypes.h',
     'gfxUserFontSet.h',
     'gfxUtils.h',
-    'gfxVR.h',
     'GraphicsFilter.h',
     'RoundedRect.h',
     'SoftwareVsyncSource.h',
     'VsyncSource.h',
 ]
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android':
     EXPORTS += [
@@ -239,17 +238,16 @@ UNIFIED_SOURCES += [
     'gfxReusableSharedImageSurfaceWrapper.cpp',
     'gfxScriptItemizer.cpp',
     'gfxSkipChars.cpp',
     'gfxSVGGlyphs.cpp',
     'gfxTeeSurface.cpp',
     'gfxTextRun.cpp',
     'gfxUserFontSet.cpp',
     'gfxUtils.cpp',
-    'gfxVR.cpp',
     'nsUnicodeRange.cpp',
     'SoftwareVsyncSource.cpp',
     'VsyncSource.cpp',
 ]
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
     UNIFIED_SOURCES += [
         'gfxMacPlatformFontList.mm',
deleted file mode 100644
--- a/gfx/thebes/ovr_capi_dynamic.h
+++ /dev/null
@@ -1,228 +0,0 @@
-/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/* This file contains just the needed struct definitions for
- * interacting with the Oculus VR C API, without needing to #include
- * OVR_CAPI.h directly.  Note that it uses the same type names as the
- * CAPI, and cannot be #included at the same time as OVR_CAPI.h.  It
- * does not include the entire C API, just want's needed.
- */
-
-#ifdef OVR_CAPI_h
-#warning OVR_CAPI.h included before ovr_capi_dynamic.h, skpping this
-#define mozilla_ovr_capi_dynamic_h_
-#endif
-
-#ifndef mozilla_ovr_capi_dynamic_h_
-#define mozilla_ovr_capi_dynamic_h_
-
-#define OVR_CAPI_LIMITED_MOZILLA 1
-
-#ifdef __cplusplus 
-extern "C" {
-#endif
-
-typedef char ovrBool;
-typedef struct { int x, y; } ovrVector2i;
-typedef struct { int w, h; } ovrSizei;
-typedef struct { ovrVector2i Pos; ovrSizei Size; } ovrRecti;
-typedef struct { float x, y, z, w; } ovrQuatf;
-typedef struct { float x, y; } ovrVector2f;
-typedef struct { float x, y, z; } ovrVector3f;
-typedef struct { float M[4][4]; } ovrMatrix4f;
-
-typedef struct {
-  ovrQuatf Orientation;
-  ovrVector3f Position;
-} ovrPosef;
-
-typedef struct {
-  ovrPosef ThePose;
-  ovrVector3f AngularVelocity;
-  ovrVector3f LinearVelocity;
-  ovrVector3f AngularAcceleration;
-  ovrVector3f LinearAcceleration;
-  double TimeInSeconds;
-} ovrPoseStatef;
-
-typedef struct {
-  float UpTan;
-  float DownTan;
-  float LeftTan;
-  float RightTan;
-} ovrFovPort;
-
-typedef enum {
-  ovrHmd_None             = 0,    
-  ovrHmd_DK1              = 3,
-  ovrHmd_DKHD             = 4,
-  ovrHmd_DK2              = 6,
-  ovrHmd_Other
-} ovrHmdType;
-
-typedef enum {
-  ovrHmdCap_Present           = 0x0001,
-  ovrHmdCap_Available         = 0x0002,
-  ovrHmdCap_Captured          = 0x0004,
-  ovrHmdCap_ExtendDesktop     = 0x0008,
-  ovrHmdCap_DisplayOff        = 0x0040,
-  ovrHmdCap_LowPersistence    = 0x0080,
-  ovrHmdCap_DynamicPrediction = 0x0200,
-  ovrHmdCap_NoVSync           = 0x1000,
-  ovrHmdCap_NoMirrorToWindow  = 0x2000
-} ovrHmdCapBits;
-
-typedef enum
-{
-  ovrTrackingCap_Orientation      = 0x0010,
-  ovrTrackingCap_MagYawCorrection = 0x0020,
-  ovrTrackingCap_Position         = 0x0040,
-  ovrTrackingCap_Idle             = 0x0100
-} ovrTrackingCaps;
-
-typedef enum {
-  ovrDistortionCap_Chromatic = 0x01,
-  ovrDistortionCap_TimeWarp  = 0x02,
-  ovrDistortionCap_Vignette  = 0x08,
-  ovrDistortionCap_NoRestore = 0x10,
-  ovrDistortionCap_FlipInput = 0x20,
-  ovrDistortionCap_SRGB      = 0x40,
-  ovrDistortionCap_Overdrive = 0x80,
-  ovrDistortionCap_ProfileNoTimewarpSpinWaits = 0x10000
-} ovrDistortionCaps;
-
-typedef enum {
-  ovrEye_Left  = 0,
-  ovrEye_Right = 1,
-  ovrEye_Count = 2
-} ovrEyeType;
-
-typedef struct ovrHmdDesc_ {
-  void* Handle;
-  ovrHmdType  Type;
-  const char* ProductName;    
-  const char* Manufacturer;
-  short VendorId;
-  short ProductId;
-  char SerialNumber[24];
-  short FirmwareMajor;
-  short FirmwareMinor;
-  float CameraFrustumHFovInRadians;
-  float CameraFrustumVFovInRadians;
-  float CameraFrustumNearZInMeters;
-  float CameraFrustumFarZInMeters;
-
-  unsigned int HmdCaps;
-  unsigned int TrackingCaps;
-  unsigned int DistortionCaps;
-
-  ovrFovPort  DefaultEyeFov[ovrEye_Count];
-  ovrFovPort  MaxEyeFov[ovrEye_Count];
-  ovrEyeType  EyeRenderOrder[ovrEye_Count];
-
-  ovrSizei    Resolution;
-  ovrVector2i WindowsPos;
-
-  const char* DisplayDeviceName;
-  int         DisplayId;
-} ovrHmdDesc;
-
-typedef const ovrHmdDesc* ovrHmd;
-
-typedef enum {
-  ovrStatus_OrientationTracked    = 0x0001,
-  ovrStatus_PositionTracked       = 0x0002,
-  ovrStatus_CameraPoseTracked     = 0x0004,
-  ovrStatus_PositionConnected     = 0x0020,
-  ovrStatus_HmdConnected          = 0x0080
-} ovrStatusBits;
-
-typedef struct ovrSensorData_ {
-  ovrVector3f    Accelerometer;
-  ovrVector3f    Gyro;
-  ovrVector3f    Magnetometer;
-  float          Temperature;
-  float          TimeInSeconds;
-} ovrSensorData;
-
-
-typedef struct ovrTrackingState_ {
-  ovrPoseStatef HeadPose;
-  ovrPosef CameraPose;
-  ovrPosef LeveledCameraPose;
-  ovrSensorData RawSensorData;
-  unsigned int StatusFlags;
-  double LastVisionProcessingTime;
-  double LastVisionFrameLatency;
-  uint32_t LastCameraFrameCounter;
-} ovrTrackingState;
-
-typedef struct ovrFrameTiming_ {
-  float DeltaSeconds;
-  double ThisFrameSeconds;
-  double TimewarpPointSeconds;
-  double NextFrameSeconds;
-  double ScanoutMidpointSeconds;
-  double EyeScanoutSeconds[2];    
-} ovrFrameTiming;
-
-typedef struct ovrEyeRenderDesc_ {
-  ovrEyeType  Eye;        
-  ovrFovPort  Fov;
-  ovrRecti DistortedViewport;
-  ovrVector2f PixelsPerTanAngleAtCenter;
-  ovrVector3f ViewAdjust;