Merge inbound to central, a=merge
authorWes Kocher <wkocher@mozilla.com>
Tue, 15 Sep 2015 17:16:24 -0700
changeset 262644 df10a3f6060f208bc3f5f0e1d9965e083076a952
parent 262643 bd52dfa335821853c69c2fa559edf3e59d55c6f5 (current diff)
parent 262624 2ad7f8d8c0421a8dcccafabb71a807a9337d2abc (diff)
child 262645 dbfddd6efb5d646d4906d660989bc9d6ed509ab1
child 262674 9891fadcb68e558ae2b947c4b2c4d4ede6ee6b32
child 262691 3e8dde8f8c174cce2c0b65c951808f88e35d1875
child 262747 ab6060fa1b89045e4ae3f2a9bcbde37d30ad8cda
push id15198
push userkwierso@gmail.com
push dateWed, 16 Sep 2015 00:21:31 +0000
treeherderfx-team@dbfddd6efb5d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone43.0a1
Merge inbound to central, a=merge
dom/workers/MessagePort.cpp
dom/workers/MessagePort.h
testing/web-platform/meta/service-workers/cache-storage/window/cache-add.https.html.ini
testing/web-platform/meta/service-workers/cache-storage/window/cache-delete.https.html.ini
testing/web-platform/meta/service-workers/cache-storage/window/cache-storage-keys.https.html.ini
testing/web-platform/meta/service-workers/cache-storage/window/cache-storage.https.html.ini
testing/web-platform/meta/service-workers/cache-storage/window/sandboxed-iframes.https.html.ini
--- a/accessible/base/AccEvent.cpp
+++ b/accessible/base/AccEvent.cpp
@@ -99,18 +99,19 @@ AccReorderEvent::IsShowHideEventTarget(c
   return 0;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // AccHideEvent
 ////////////////////////////////////////////////////////////////////////////////
 
 AccHideEvent::
-  AccHideEvent(Accessible* aTarget, nsINode* aTargetNode) :
-  AccMutationEvent(::nsIAccessibleEvent::EVENT_HIDE, aTarget, aTargetNode)
+  AccHideEvent(Accessible* aTarget, nsINode* aTargetNode, bool aNeedsShutdown) :
+  AccMutationEvent(::nsIAccessibleEvent::EVENT_HIDE, aTarget, aTargetNode),
+  mNeedsShutdown(aNeedsShutdown)
 {
   mNextSibling = mAccessible->NextSibling();
   mPrevSibling = mAccessible->PrevSibling();
 }
 
 
 ////////////////////////////////////////////////////////////////////////////////
 // AccShowEvent
--- a/accessible/base/AccEvent.h
+++ b/accessible/base/AccEvent.h
@@ -245,31 +245,34 @@ protected:
 
 
 /**
  * Accessible hide event.
  */
 class AccHideEvent: public AccMutationEvent
 {
 public:
-  AccHideEvent(Accessible* aTarget, nsINode* aTargetNode);
+  AccHideEvent(Accessible* aTarget, nsINode* aTargetNode,
+               bool aNeedsShutdown = true);
 
   // Event
   static const EventGroup kEventGroup = eHideEvent;
   virtual unsigned int GetEventGroups() const override
   {
     return AccMutationEvent::GetEventGroups() | (1U << eHideEvent);
   }
 
   // AccHideEvent
   Accessible* TargetParent() const { return mParent; }
   Accessible* TargetNextSibling() const { return mNextSibling; }
   Accessible* TargetPrevSibling() const { return mPrevSibling; }
+  bool NeedsShutdown() const { return mNeedsShutdown; }
 
 protected:
+  bool mNeedsShutdown;
   nsRefPtr<Accessible> mNextSibling;
   nsRefPtr<Accessible> mPrevSibling;
 
   friend class EventQueue;
 };
 
 
 /**
--- a/accessible/base/EventQueue.cpp
+++ b/accessible/base/EventQueue.cpp
@@ -541,15 +541,17 @@ EventQueue::ProcessEventQueue()
       // Fire text change events.
       AccMutationEvent* mutationEvent = downcast_accEvent(event);
       if (mutationEvent) {
         if (mutationEvent->mTextChangeEvent)
           nsEventShell::FireEvent(mutationEvent->mTextChangeEvent);
       }
     }
 
-    if (event->mEventType == nsIAccessibleEvent::EVENT_HIDE)
+    AccHideEvent* hideEvent = downcast_accEvent(event);
+    if (hideEvent && hideEvent->NeedsShutdown()) {
       mDocument->ShutdownChildrenInSubtree(event->mAccessible);
+    }
 
     if (!mDocument)
       return;
   }
 }
--- a/accessible/base/NotificationController.cpp
+++ b/accessible/base/NotificationController.cpp
@@ -104,30 +104,30 @@ NotificationController::ScheduleContentI
   nsRefPtr<ContentInsertion> insertion = new ContentInsertion(mDocument,
                                                               aContainer);
   if (insertion && insertion->InitChildList(aStartChildNode, aEndChildNode) &&
       mContentInsertions.AppendElement(insertion)) {
     ScheduleProcessing();
   }
 }
 
-////////////////////////////////////////////////////////////////////////////////
-// NotificationCollector: protected
-
 void
 NotificationController::ScheduleProcessing()
 {
   // If notification flush isn't planed yet start notification flush
   // asynchronously (after style and layout).
   if (mObservingState == eNotObservingRefresh) {
     if (mPresShell->AddRefreshObserver(this, Flush_Display))
       mObservingState = eRefreshObserving;
   }
 }
 
+////////////////////////////////////////////////////////////////////////////////
+// NotificationCollector: protected
+
 bool
 NotificationController::IsUpdatePending()
 {
   return mPresShell->IsLayoutFlushObserver() ||
     mObservingState == eRefreshProcessingForUpdate ||
     mContentInsertions.Length() != 0 || mNotifications.Length() != 0 ||
     mTextHash.Count() != 0 ||
     !mDocument->HasLoadState(DocAccessible::eTreeConstructed);
--- a/accessible/base/NotificationController.h
+++ b/accessible/base/NotificationController.h
@@ -3,16 +3,18 @@
  * 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_a11y_NotificationController_h_
 #define mozilla_a11y_NotificationController_h_
 
 #include "EventQueue.h"
 
+#include "mozilla/IndexSequence.h"
+#include "mozilla/Tuple.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsRefreshDriver.h"
 
 #ifdef A11Y_LOG
 #include "Logging.h"
 #endif
 
 namespace mozilla {
@@ -49,42 +51,42 @@ private:
 
 /**
  * Template class for generic notification.
  *
  * @note  Instance is kept as a weak ref, the caller must guarantee it exists
  *        longer than the document accessible owning the notification controller
  *        that this notification is processed by.
  */
-template<class Class, class Arg>
+template<class Class, class ... Args>
 class TNotification : public Notification
 {
 public:
-  typedef void (Class::*Callback)(Arg*);
+  typedef void (Class::*Callback)(Args* ...);
 
-  TNotification(Class* aInstance, Callback aCallback, Arg* aArg) :
-    mInstance(aInstance), mCallback(aCallback), mArg(aArg) { }
+  TNotification(Class* aInstance, Callback aCallback, Args* ... aArgs) :
+    mInstance(aInstance), mCallback(aCallback), mArgs(aArgs...) { }
   virtual ~TNotification() { mInstance = nullptr; }
 
   virtual void Process() override
-  {
-    (mInstance->*mCallback)(mArg);
-
-    mInstance = nullptr;
-    mCallback = nullptr;
-    mArg = nullptr;
-  }
+    { ProcessHelper(typename IndexSequenceFor<Args...>::Type()); }
 
 private:
   TNotification(const TNotification&);
   TNotification& operator = (const TNotification&);
 
+  template <size_t... Indices>
+    void ProcessHelper(IndexSequence<Indices...>)
+  {
+     (mInstance->*mCallback)(Get<Indices>(mArgs)...);
+  }
+
   Class* mInstance;
   Callback mCallback;
-  nsRefPtr<Arg> mArg;
+  Tuple<nsRefPtr<Args> ...> mArgs;
 };
 
 /**
  * Used to process notifications from core for the document accessible.
  */
 class NotificationController final : public EventQueue,
                                      public nsARefreshObserver
 {
@@ -127,16 +129,22 @@ public:
   /**
    * Pend accessible tree update for content insertion.
    */
   void ScheduleContentInsertion(Accessible* aContainer,
                                 nsIContent* aStartChildNode,
                                 nsIContent* aEndChildNode);
 
   /**
+   * Start to observe refresh to make notifications and events processing after
+   * layout.
+   */
+  void ScheduleProcessing();
+
+  /**
    * Process the generic notification synchronously if there are no pending
    * layout changes and no notifications are pending or being processed right
    * now. Otherwise, queue it up to process asynchronously.
    *
    * @note  The caller must guarantee that the given instance still exists when
    *        the notification is processed.
    */
   template<class Class, class Arg>
@@ -160,45 +168,38 @@ public:
   }
 
   /**
    * Schedule the generic notification to process asynchronously.
    *
    * @note  The caller must guarantee that the given instance still exists when
    *        the notification is processed.
    */
-  template<class Class, class Arg>
+  template<class Class>
   inline void ScheduleNotification(Class* aInstance,
-                                   typename TNotification<Class, Arg>::Callback aMethod,
-                                   Arg* aArg)
+                                   typename TNotification<Class>::Callback aMethod)
   {
     nsRefPtr<Notification> notification =
-      new TNotification<Class, Arg>(aInstance, aMethod, aArg);
+      new TNotification<Class>(aInstance, aMethod);
     if (notification && mNotifications.AppendElement(notification))
       ScheduleProcessing();
   }
 
 #ifdef DEBUG
   bool IsUpdating() const
     { return mObservingState == eRefreshProcessingForUpdate; }
 #endif
 
 protected:
   virtual ~NotificationController();
 
   nsCycleCollectingAutoRefCnt mRefCnt;
   NS_DECL_OWNINGTHREAD
 
   /**
-   * Start to observe refresh to make notifications and events processing after
-   * layout.
-   */
-  void ScheduleProcessing();
-
-  /**
    * Return true if the accessible tree state update is pending.
    */
   bool IsUpdatePending();
 
 private:
   NotificationController(const NotificationController&);
   NotificationController& operator = (const NotificationController&);
 
--- a/accessible/base/TreeWalker.cpp
+++ b/accessible/base/TreeWalker.cpp
@@ -1,16 +1,17 @@
 /* -*- Mode: C++; tab-width: 2; 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 "TreeWalker.h"
 
 #include "Accessible.h"
+#include "AccIterator.h"
 #include "nsAccessibilityService.h"
 #include "DocAccessible.h"
 
 #include "mozilla/dom/ChildIterator.h"
 #include "mozilla/dom/Element.h"
 
 using namespace mozilla;
 using namespace mozilla::a11y;
@@ -45,30 +46,26 @@ TreeWalker::~TreeWalker()
 // TreeWalker: private
 
 Accessible*
 TreeWalker::NextChild()
 {
   if (mStateStack.IsEmpty())
     return nullptr;
 
-  dom::AllChildrenIterator* top = &mStateStack[mStateStack.Length() - 1];
+  ChildrenIterator* top = &mStateStack[mStateStack.Length() - 1];
   while (top) {
-    while (nsIContent* childNode = top->GetNextChild()) {
-      bool isSubtreeHidden = false;
-      Accessible* accessible = mFlags & eWalkCache ?
-        mDoc->GetAccessible(childNode) :
-        GetAccService()->GetOrCreateAccessible(childNode, mContext,
-                                               &isSubtreeHidden);
-
-      if (accessible)
-        return accessible;
+    Accessible* child = nullptr;
+    bool skipSubtree = false;
+    while (nsIContent* childNode = Next(top, &child, &skipSubtree)) {
+      if (child)
+        return child;
 
       // Walk down into subtree to find accessibles.
-      if (!isSubtreeHidden && childNode->IsElement())
+      if (!skipSubtree && childNode->IsElement())
         top = PushState(childNode);
     }
 
     top = PopState();
   }
 
   // If we traversed the whole subtree of the anchor node. Move to next node
   // relative anchor node within the context subtree if possible.
@@ -77,34 +74,73 @@ TreeWalker::NextChild()
 
   nsINode* contextNode = mContext->GetNode();
   while (mAnchorNode != contextNode) {
     nsINode* parentNode = mAnchorNode->GetFlattenedTreeParent();
     if (!parentNode || !parentNode->IsElement())
       return nullptr;
 
     nsIContent* parent = parentNode->AsElement();
-    top = mStateStack.AppendElement(dom::AllChildrenIterator(parent,
-                                                             mChildFilter));
-    while (nsIContent* childNode = top->GetNextChild()) {
+    top = PushState(parent);
+    while (nsIContent* childNode = Next(top)) {
       if (childNode == mAnchorNode) {
         mAnchorNode = parent;
         return NextChild();
       }
     }
 
     // XXX We really should never get here, it means we're trying to find an
     // accessible for a dom node where iterating over its parent's children
     // doesn't return it. However this sometimes happens when we're asked for
     // the nearest accessible to place holder content which we ignore.
     mAnchorNode = parent;
   }
 
   return nullptr;
 }
 
-dom::AllChildrenIterator*
+nsIContent*
+TreeWalker::Next(ChildrenIterator* aIter, Accessible** aAccesible,
+                 bool* aSkipSubtree)
+{
+  nsIContent* childEl = aIter->mDOMIter.GetNextChild();
+  if (!aAccesible)
+    return childEl;
+
+  *aAccesible = nullptr;
+  *aSkipSubtree = false;
+
+  if (childEl) {
+    Accessible* accessible = mFlags & eWalkCache ?
+      mDoc->GetAccessible(childEl) :
+      GetAccService()->GetOrCreateAccessible(childEl, mContext, aSkipSubtree);
+
+    // Ignore the accessible and its subtree if it was repositioned by means of
+    // aria-owns.
+    if (accessible) {
+      if (accessible->IsRepositioned()) {
+        *aSkipSubtree = true;
+      } else {
+        *aAccesible = accessible;
+      }
+    }
+    return childEl;
+  }
+
+  // At last iterate over ARIA owned children.
+  Accessible* parent = mDoc->GetAccessible(aIter->mDOMIter.Parent());
+  if (parent) {
+    Accessible* child = mDoc->ARIAOwnedAt(parent, aIter->mARIAOwnsIdx++);
+    if (child) {
+      *aAccesible = child;
+      return child->GetContent();
+    }
+  }
+  return nullptr;
+}
+
+TreeWalker::ChildrenIterator*
 TreeWalker::PopState()
 {
   size_t length = mStateStack.Length();
   mStateStack.RemoveElementAt(length - 1);
   return mStateStack.IsEmpty() ? nullptr : &mStateStack[mStateStack.Length() - 1];
 }
--- a/accessible/base/TreeWalker.h
+++ b/accessible/base/TreeWalker.h
@@ -52,37 +52,47 @@ public:
    */
   Accessible* NextChild();
 
 private:
   TreeWalker();
   TreeWalker(const TreeWalker&);
   TreeWalker& operator =(const TreeWalker&);
 
+  struct ChildrenIterator {
+    ChildrenIterator(nsIContent* aNode, uint32_t aFilter) :
+      mDOMIter(aNode, aFilter), mARIAOwnsIdx(0) { }
+
+    dom::AllChildrenIterator mDOMIter;
+    uint32_t mARIAOwnsIdx;
+  };
+
+  nsIContent* Next(ChildrenIterator* aIter, Accessible** aAccessible = nullptr,
+                   bool* aSkipSubtree = nullptr);
+
   /**
    * Create new state for the given node and push it on top of stack.
    *
    * @note State stack is used to navigate up/down the DOM subtree during
    *        accessible children search.
    */
-  dom::AllChildrenIterator* PushState(nsIContent* aContent)
+  ChildrenIterator* PushState(nsIContent* aContent)
   {
-    return mStateStack.AppendElement(dom::AllChildrenIterator(aContent,
-                                                              mChildFilter));
+    return mStateStack.AppendElement(ChildrenIterator(aContent, mChildFilter));
   }
 
   /**
    * Pop state from stack.
    */
-  dom::AllChildrenIterator* PopState();
+  ChildrenIterator* PopState();
 
   DocAccessible* mDoc;
   Accessible* mContext;
   nsIContent* mAnchorNode;
-  nsAutoTArray<dom::AllChildrenIterator, 20> mStateStack;
+  nsAutoTArray<ChildrenIterator, 20> mStateStack;
   int32_t mChildFilter;
   uint32_t mFlags;
 };
 
 } // namespace a11y
 } // namespace mozilla
 
 #endif // mozilla_a11y_TreeWalker_h_
--- a/accessible/generic/Accessible.cpp
+++ b/accessible/generic/Accessible.cpp
@@ -1969,18 +1969,18 @@ Accessible::NativeName(nsString& aName)
 void
 Accessible::BindToParent(Accessible* aParent, uint32_t aIndexInParent)
 {
   NS_PRECONDITION(aParent, "This method isn't used to set null parent!");
 
   if (mParent) {
     if (mParent != aParent) {
       NS_ERROR("Adopting child!");
+      mParent->InvalidateChildrenGroupInfo();
       mParent->RemoveChild(this);
-      mParent->InvalidateChildrenGroupInfo();
     } else {
       NS_ERROR("Binding to the same parent!");
       return;
     }
   }
 
   mParent = aParent;
   mIndexInParent = aIndexInParent;
--- a/accessible/generic/Accessible.h
+++ b/accessible/generic/Accessible.h
@@ -155,16 +155,18 @@ public:
    */
   virtual nsINode* GetNode() const;
   inline already_AddRefed<nsIDOMNode> DOMNode() const
   {
     nsCOMPtr<nsIDOMNode> DOMNode = do_QueryInterface(GetNode());
     return DOMNode.forget();
   }
   nsIContent* GetContent() const { return mContent; }
+  mozilla::dom::Element* Elm() const
+    { return mContent && mContent->IsElement() ? mContent->AsElement() : nullptr; }
 
   /**
    * Return node type information of DOM node associated with the accessible.
    */
   bool IsContent() const
     { return GetNode() && GetNode()->IsNodeOfType(nsINode::eCONTENT); }
 
   /**
@@ -895,31 +897,43 @@ public:
   {
     if (aIsSurviving)
       mStateFlags |= eSurvivingInUpdate;
     else
       mStateFlags &= ~eSurvivingInUpdate;
   }
 
   /**
+   * Get/set repositioned bit indicating that the accessible was moved in
+   * the accessible tree, i.e. the accessible tree structure differs from DOM.
+   */
+  bool IsRepositioned() const { return mStateFlags & eRepositioned; }
+  void SetRepositioned(bool aRepositioned)
+  {
+    if (aRepositioned)
+      mStateFlags |= eRepositioned;
+    else
+      mStateFlags &= ~eRepositioned;
+  }
+
+  /**
    * Return true if this accessible has a parent whose name depends on this
    * accessible.
    */
   bool HasNameDependentParent() const
     { return mContextFlags & eHasNameDependentParent; }
 
   /**
    * Return true if aria-hidden="true" is applied to the accessible or inherited
    * from the parent.
    */
   bool IsARIAHidden() const { return mContextFlags & eARIAHidden; }
   void SetARIAHidden(bool aIsDefined);
 
 protected:
-
   virtual ~Accessible();
 
   /**
    * Return the accessible name provided by native markup. It doesn't take
    * into account ARIA markup used to specify the name.
    */
   virtual mozilla::a11y::ENameValueFlag NativeName(nsString& aName);
 
@@ -985,18 +999,19 @@ protected:
     eIsNotInDocument = 1 << 1, // accessible is not in document
     eSharedNode = 1 << 2, // accessible shares DOM node from another accessible
     eNotNodeMapEntry = 1 << 3, // accessible shouldn't be in document node map
     eHasNumericValue = 1 << 4, // accessible has a numeric value
     eGroupInfoDirty = 1 << 5, // accessible needs to update group info
     eSubtreeMutating = 1 << 6, // subtree is being mutated
     eIgnoreDOMUIEvent = 1 << 7, // don't process DOM UI events for a11y events
     eSurvivingInUpdate = 1 << 8, // parent drops children to recollect them
+    eRepositioned = 1 << 9, // accessible was moved in tree
 
-    eLastStateFlag = eSurvivingInUpdate
+    eLastStateFlag = eRepositioned
   };
 
   /**
    * Flags used for contextual information about the accessible.
    */
   enum ContextFlags {
     eHasNameDependentParent = 1 << 0, // Parent's name depends on this accessible.
     eARIAHidden = 1 << 1,
@@ -1101,17 +1116,17 @@ protected:
   nsCOMPtr<nsIContent> mContent;
   DocAccessible* mDoc;
 
   nsRefPtr<Accessible> mParent;
   nsTArray<nsRefPtr<Accessible> > mChildren;
   int32_t mIndexInParent;
 
   static const uint8_t kChildrenFlagsBits = 2;
-  static const uint8_t kStateFlagsBits = 9;
+  static const uint8_t kStateFlagsBits = 10;
   static const uint8_t kContextFlagsBits = 2;
   static const uint8_t kTypeBits = 6;
   static const uint8_t kGenericTypesBits = 14;
 
   /**
    * Keep in sync with ChildrenFlags, StateFlags, ContextFlags, and AccTypes.
    */
   uint32_t mChildrenFlags : kChildrenFlagsBits;
--- a/accessible/generic/DocAccessible.cpp
+++ b/accessible/generic/DocAccessible.cpp
@@ -702,17 +702,17 @@ DocAccessible::AttributeWillChange(nsIDo
 
     accessible = this;
   }
 
   // Update dependent IDs cache. Take care of elements that are accessible
   // because dependent IDs cache doesn't contain IDs from non accessible
   // elements.
   if (aModType != nsIDOMMutationEvent::ADDITION)
-    RemoveDependentIDsFor(aElement, aAttribute);
+    RemoveDependentIDsFor(accessible, aAttribute);
 
   // Store the ARIA attribute old value so that it can be used after
   // attribute change. Note, we assume there's no nested ARIA attribute
   // changes. If this happens then we should end up with keeping a stack of
   // old values.
 
   // XXX TODO: bugs 472142, 472143.
   // Here we will want to cache whatever attribute values we are interested
@@ -764,17 +764,17 @@ DocAccessible::AttributeChanged(nsIDocum
 
   // Update dependent IDs cache. Take care of accessible elements because no
   // accessible element means either the element is not accessible at all or
   // its accessible will be created later. It doesn't make sense to keep
   // dependent IDs for non accessible elements. For the second case we'll update
   // dependent IDs cache when its accessible is created.
   if (aModType == nsIDOMMutationEvent::MODIFICATION ||
       aModType == nsIDOMMutationEvent::ADDITION) {
-    AddDependentIDsFor(aElement, aAttribute);
+    AddDependentIDsFor(accessible, aAttribute);
   }
 }
 
 // DocAccessible protected member
 void
 DocAccessible::AttributeChangedImpl(Accessible* aAccessible,
                                     int32_t aNameSpaceID, nsIAtom* aAttribute)
 {
@@ -1236,19 +1236,17 @@ DocAccessible::BindToDocument(Accessible
   if (aAccessible->IsNodeMapEntry())
     mNodeToAccessibleMap.Put(aAccessible->GetNode(), aAccessible);
 
   // Put into unique ID cache.
   mAccessibleCache.Put(aAccessible->UniqueID(), aAccessible);
 
   aAccessible->SetRoleMapEntry(aRoleMapEntry);
 
-  nsIContent* content = aAccessible->GetContent();
-  if (content && content->IsElement())
-    AddDependentIDsFor(content->AsElement());
+  AddDependentIDsFor(aAccessible);
 }
 
 void
 DocAccessible::UnbindFromDocument(Accessible* aAccessible)
 {
   NS_ASSERTION(mAccessibleCache.GetWeak(aAccessible->UniqueID()),
                "Unbinding the unbound accessible!");
 
@@ -1333,16 +1331,59 @@ DocAccessible::ProcessInvalidationList()
     if (!HasAccessible(content)) {
       Accessible* container = GetContainerAccessible(content);
       if (container)
         UpdateTreeOnInsertion(container);
     }
   }
 
   mInvalidationList.Clear();
+
+  // Alter the tree according to aria-owns (seize the trees).
+  for (uint32_t idx = 0; idx < mARIAOwnsInvalidationList.Length(); idx++) {
+    Accessible* owner = mARIAOwnsInvalidationList[idx].mOwner;
+    Accessible* child = GetAccessible(mARIAOwnsInvalidationList[idx].mChild);
+    if (!child) {
+      continue;
+    }
+
+    // XXX: update context flags
+    {
+      Accessible* oldParent = child->Parent();
+      nsRefPtr<AccReorderEvent> reorderEvent = new AccReorderEvent(oldParent);
+      nsRefPtr<AccMutationEvent> hideEvent =
+        new AccHideEvent(child, child->GetContent(), false);
+      FireDelayedEvent(hideEvent);
+      reorderEvent->AddSubMutationEvent(hideEvent);
+
+      AutoTreeMutation mut(oldParent);
+      oldParent->RemoveChild(child);
+
+      MaybeNotifyOfValueChange(oldParent);
+      FireDelayedEvent(reorderEvent);
+    }
+
+    {
+      nsRefPtr<AccReorderEvent> reorderEvent = new AccReorderEvent(owner);
+      nsRefPtr<AccMutationEvent> showEvent =
+        new AccShowEvent(child, child->GetContent());
+      FireDelayedEvent(showEvent);
+      reorderEvent->AddSubMutationEvent(showEvent);
+
+      AutoTreeMutation mut(owner);
+      owner->AppendChild(child);
+
+      MaybeNotifyOfValueChange(owner);
+      FireDelayedEvent(reorderEvent);
+    }
+
+    child->SetRepositioned(true);
+  }
+
+  mARIAOwnsInvalidationList.Clear();
 }
 
 Accessible*
 DocAccessible::GetAccessibleEvenIfNotInMap(nsINode* aNode) const
 {
 if (!aNode->IsContent() || !aNode->AsContent()->IsHTMLElement(nsGkAtoms::area))
     return GetAccessible(aNode);
 
@@ -1491,104 +1532,207 @@ DocAccessible::ProcessLoad()
 
   // Fire busy state change event.
   nsRefPtr<AccEvent> stateEvent =
     new AccStateChangeEvent(this, states::BUSY, false);
   FireDelayedEvent(stateEvent);
 }
 
 void
-DocAccessible::AddDependentIDsFor(dom::Element* aRelProviderElm,
-                                  nsIAtom* aRelAttr)
+DocAccessible::AddDependentIDsFor(Accessible* aRelProvider, nsIAtom* aRelAttr)
 {
+  dom::Element* relProviderEl = aRelProvider->Elm();
+  if (!relProviderEl)
+    return;
+
   for (uint32_t idx = 0; idx < kRelationAttrsLen; idx++) {
     nsIAtom* relAttr = *kRelationAttrs[idx];
     if (aRelAttr && aRelAttr != relAttr)
       continue;
 
     if (relAttr == nsGkAtoms::_for) {
-      if (!aRelProviderElm->IsAnyOfHTMLElements(nsGkAtoms::label,
-                                                nsGkAtoms::output))
+      if (!relProviderEl->IsAnyOfHTMLElements(nsGkAtoms::label,
+                                               nsGkAtoms::output))
         continue;
 
     } else if (relAttr == nsGkAtoms::control) {
-      if (!aRelProviderElm->IsAnyOfXULElements(nsGkAtoms::label,
-                                               nsGkAtoms::description))
+      if (!relProviderEl->IsAnyOfXULElements(nsGkAtoms::label,
+                                              nsGkAtoms::description))
         continue;
     }
 
-    IDRefsIterator iter(this, aRelProviderElm, relAttr);
+    IDRefsIterator iter(this, relProviderEl, relAttr);
     while (true) {
       const nsDependentSubstring id = iter.NextID();
       if (id.IsEmpty())
         break;
 
       AttrRelProviderArray* providers = mDependentIDsHash.Get(id);
       if (!providers) {
         providers = new AttrRelProviderArray();
         if (providers) {
           mDependentIDsHash.Put(id, providers);
         }
       }
 
       if (providers) {
         AttrRelProvider* provider =
-          new AttrRelProvider(relAttr, aRelProviderElm);
+          new AttrRelProvider(relAttr, relProviderEl);
         if (provider) {
           providers->AppendElement(provider);
 
           // We've got here during the children caching. If the referenced
           // content is not accessible then store it to pend its container
           // children invalidation (this happens immediately after the caching
           // is finished).
           nsIContent* dependentContent = iter.GetElem(id);
-          if (dependentContent && !HasAccessible(dependentContent)) {
-            mInvalidationList.AppendElement(dependentContent);
+          if (dependentContent) {
+            if (!HasAccessible(dependentContent)) {
+              mInvalidationList.AppendElement(dependentContent);
+            }
+
+            if (relAttr == nsGkAtoms::aria_owns) {
+              // Dependent content cannot point to other aria-owns content or
+              // their parents. Ignore it if so.
+              // XXX: note, this alg may make invalid the scenario when X owns Y
+              // and Y owns Z, we should have something smarter to handle that.
+              bool isvalid = true;
+              for (auto it = mARIAOwnsHash.Iter(); !it.Done(); it.Next()) {
+                Accessible* owner = it.Key();
+                nsIContent* parentEl = owner->GetContent();
+                while (parentEl && parentEl != dependentContent) {
+                  parentEl = parentEl->GetParent();
+                }
+                if (parentEl) {
+                  isvalid = false;
+                  break;
+                }
+              }
+              if (isvalid) {
+                // ARIA owns also cannot refer to itself or a parent.
+                nsIContent* parentEl = relProviderEl;
+                while (parentEl && parentEl != dependentContent) {
+                  parentEl = parentEl->GetParent();
+                }
+                if (parentEl) {
+                  isvalid = false;
+                }
+
+                if (isvalid) {
+                  nsTArray<nsIContent*>* list =
+                    mARIAOwnsHash.LookupOrAdd(aRelProvider);
+                  list->AppendElement(dependentContent);
+
+                  mARIAOwnsInvalidationList.AppendElement(
+                    ARIAOwnsPair(aRelProvider, dependentContent));
+                }
+              }
+            }
           }
         }
       }
     }
 
     // If the relation attribute is given then we don't have anything else to
     // check.
     if (aRelAttr)
       break;
   }
+
+  // Make sure to schedule the tree update if needed.
+  mNotificationController->ScheduleProcessing();
 }
 
 void
-DocAccessible::RemoveDependentIDsFor(dom::Element* aRelProviderElm,
+DocAccessible::RemoveDependentIDsFor(Accessible* aRelProvider,
                                      nsIAtom* aRelAttr)
 {
+  dom::Element* relProviderElm = aRelProvider->Elm();
+  if (!relProviderElm)
+    return;
+
   for (uint32_t idx = 0; idx < kRelationAttrsLen; idx++) {
     nsIAtom* relAttr = *kRelationAttrs[idx];
     if (aRelAttr && aRelAttr != *kRelationAttrs[idx])
       continue;
 
-    IDRefsIterator iter(this, aRelProviderElm, relAttr);
+    IDRefsIterator iter(this, relProviderElm, relAttr);
     while (true) {
       const nsDependentSubstring id = iter.NextID();
       if (id.IsEmpty())
         break;
 
       AttrRelProviderArray* providers = mDependentIDsHash.Get(id);
       if (providers) {
         for (uint32_t jdx = 0; jdx < providers->Length(); ) {
           AttrRelProvider* provider = (*providers)[jdx];
           if (provider->mRelAttr == relAttr &&
-              provider->mContent == aRelProviderElm)
+              provider->mContent == relProviderElm)
             providers->RemoveElement(provider);
           else
             jdx++;
         }
         if (providers->Length() == 0)
           mDependentIDsHash.Remove(id);
       }
     }
 
+    // aria-owns has gone, put the children back.
+    if (relAttr == nsGkAtoms::aria_owns) {
+      nsTArray<nsIContent*>* children = mARIAOwnsHash.Get(aRelProvider);
+      if (children) {
+        nsTArray<Accessible*> containers;
+
+        // Remove ARIA owned elements from where they belonged.
+        nsRefPtr<AccReorderEvent> reorderEvent = new AccReorderEvent(aRelProvider);
+        {
+          AutoTreeMutation mut(aRelProvider);
+          for (uint32_t idx = 0; idx < children->Length(); idx++) {
+            nsIContent* childEl = children->ElementAt(idx);
+            Accessible* child = GetAccessible(childEl);
+            if (child && child->IsRepositioned()) {
+              {
+                nsRefPtr<AccMutationEvent> hideEvent =
+                  new AccHideEvent(child, childEl, false);
+                FireDelayedEvent(hideEvent);
+                reorderEvent->AddSubMutationEvent(hideEvent);
+
+                aRelProvider->RemoveChild(child);
+              }
+
+              // Collect DOM-order containers to update their trees.
+              child->SetRepositioned(false);
+              Accessible* container = GetContainerAccessible(childEl);
+              if (!containers.Contains(container)) {
+                containers.AppendElement(container);
+              }
+            }
+          }
+        }
+
+        mARIAOwnsHash.Remove(aRelProvider);
+        for (uint32_t idx = 0; idx < mARIAOwnsInvalidationList.Length();) {
+          if (mARIAOwnsInvalidationList[idx].mOwner == aRelProvider) {
+            mARIAOwnsInvalidationList.RemoveElementAt(idx);
+            continue;
+          }
+          idx++;
+        }
+
+        MaybeNotifyOfValueChange(aRelProvider);
+        FireDelayedEvent(reorderEvent);
+
+        // Reinserted previously ARIA owned elements into the tree
+        // (restore a DOM-like order).
+        for (uint32_t idx = 0; idx < containers.Length(); idx++) {
+          UpdateTreeOnInsertion(containers[idx]);
+        }
+      }
+    }
+
     // If the relation attribute is given then we don't have anything else to
     // check.
     if (aRelAttr)
       break;
   }
 }
 
 bool
@@ -1801,16 +1945,21 @@ DocAccessible::UpdateTreeOnRemoval(Acces
       if (childNode != containerNode) {
         updateFlags |= UpdateTreeInternal(child, false, reorderEvent);
       } else {
         idx++;
       }
     }
   }
 
+  // We may not have an integral DOM tree to remove all aria-owns relations
+  // from the tree. Validate all relations after timeout to workaround that.
+  mNotificationController->ScheduleNotification<DocAccessible>
+    (this, &DocAccessible::ValidateARIAOwned);
+
   // Content insertion/removal is not cause of accessible tree change.
   if (updateFlags == eNoAccessible)
     return;
 
   MaybeNotifyOfValueChange(aContainer);
   FireDelayedEvent(reorderEvent);
 }
 
@@ -1885,16 +2034,31 @@ DocAccessible::UpdateTreeInternal(Access
     FocusMgr()->DispatchFocusEvent(this, focusedAcc);
     SelectionMgr()->SetControlSelectionListener(focusedAcc->GetNode()->AsElement());
   }
 
   return updateFlags;
 }
 
 void
+DocAccessible::ValidateARIAOwned()
+{
+  for (auto it = mARIAOwnsHash.Iter(); !it.Done(); it.Next()) {
+    nsTArray<nsIContent*>* childEls = it.UserData();
+    for (uint32_t idx = 0; idx < childEls->Length(); idx++) {
+      nsIContent* childEl = childEls->ElementAt(idx);
+      Accessible* child = GetAccessible(childEl);
+      if (child && !child->GetFrame()) {
+        UpdateTreeOnRemoval(child->Parent(), childEl);
+      }
+    }
+  }
+}
+
+void
 DocAccessible::CacheChildrenInSubtree(Accessible* aRoot,
                                       Accessible** aFocusedAcc)
 {
   // If the accessible is focused then report a focus event after all related
   // mutation events.
   if (aFocusedAcc && !*aFocusedAcc &&
       FocusMgr()->HasDOMFocus(aRoot->GetContent()))
     *aFocusedAcc = aRoot;
@@ -1921,20 +2085,17 @@ DocAccessible::CacheChildrenInSubtree(Ac
       FireDelayedEvent(nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_COMPLETE, aRoot);
   }
 }
 
 void
 DocAccessible::UncacheChildrenInSubtree(Accessible* aRoot)
 {
   aRoot->mStateFlags |= eIsNotInDocument;
-
-  nsIContent* rootContent = aRoot->GetContent();
-  if (rootContent && rootContent->IsElement())
-    RemoveDependentIDsFor(rootContent->AsElement());
+  RemoveDependentIDsFor(aRoot);
 
   uint32_t count = aRoot->ContentChildCount();
   for (uint32_t idx = 0; idx < count; idx++)
     UncacheChildrenInSubtree(aRoot->ContentChildAt(idx));
 
   if (aRoot->IsNodeMapEntry() &&
       mNodeToAccessibleMap.Get(aRoot->GetNode()) == aRoot)
     mNodeToAccessibleMap.Remove(aRoot->GetNode());
--- a/accessible/generic/DocAccessible.h
+++ b/accessible/generic/DocAccessible.h
@@ -27,17 +27,17 @@ const uint32_t kDefaultCacheLength = 128
 
 namespace mozilla {
 namespace a11y {
 
 class DocManager;
 class NotificationController;
 class DocAccessibleChild;
 class RelatedAccIterator;
-template<class Class, class Arg>
+template<class Class, class ... Args>
 class TNotification;
 
 class DocAccessible : public HyperTextAccessibleWrap,
                       public nsIDocumentObserver,
                       public nsIObserver,
                       public nsIScrollPositionListener,
                       public nsSupportsWeakReference,
                       public nsIAccessiblePivotObserver
@@ -277,16 +277,32 @@ public:
   }
 
   /**
    * Return an accessible for the given node or its first accessible descendant.
    */
   Accessible* GetAccessibleOrDescendant(nsINode* aNode) const;
 
   /**
+   * Returns aria-owns seized child at the given index.
+   */
+  Accessible* ARIAOwnedAt(Accessible* aParent, uint32_t aIndex) const
+  {
+    nsTArray<nsIContent*>* childrenEl = mARIAOwnsHash.Get(aParent);
+    if (childrenEl) {
+      nsIContent* childEl = childrenEl->SafeElementAt(aIndex);
+      Accessible* child = GetAccessible(childEl);
+      if (child && child->IsRepositioned()) {
+        return child;
+      }
+    }
+    return nullptr;
+  }
+
+  /**
    * Return true if the given ID is referred by relation attribute.
    *
    * @note Different elements may share the same ID if they are hosted inside
    *       XBL bindings. Be careful the result of this method may be  senseless
    *       while it's called for XUL elements (where XBL is used widely).
    */
   bool IsDependentID(const nsAString& aID) const
     { return mDependentIDsHash.Get(aID, nullptr); }
@@ -401,28 +417,28 @@ protected:
   /**
    * Add dependent IDs pointed by accessible element by relation attribute to
    * cache. If the relation attribute is missed then all relation attributes
    * are checked.
    *
    * @param aRelProvider [in] accessible that element has relation attribute
    * @param aRelAttr     [in, optional] relation attribute
    */
-  void AddDependentIDsFor(dom::Element* aRelProviderElm,
+  void AddDependentIDsFor(Accessible* aRelProvider,
                           nsIAtom* aRelAttr = nullptr);
 
   /**
    * Remove dependent IDs pointed by accessible element by relation attribute
    * from cache. If the relation attribute is absent then all relation
    * attributes are checked.
    *
    * @param aRelProvider [in] accessible that element has relation attribute
    * @param aRelAttr     [in, optional] relation attribute
    */
-  void RemoveDependentIDsFor(dom::Element* aRelProviderElm,
+  void RemoveDependentIDsFor(Accessible* aRelProvider,
                              nsIAtom* aRelAttr = nullptr);
 
   /**
    * Update or recreate an accessible depending on a changed attribute.
    *
    * @param aElement   [in] the element the attribute was changed on
    * @param aAttribute [in] the changed attribute
    * @return            true if an action was taken on the attribute change
@@ -487,16 +503,21 @@ protected:
     eAccessible = 1,
     eAlertAccessible = 2
   };
 
   uint32_t UpdateTreeInternal(Accessible* aChild, bool aIsInsert,
                               AccReorderEvent* aReorderEvent);
 
   /**
+   * Validates all aria-owns connections and updates the tree accordingly.
+   */
+  void ValidateARIAOwned();
+
+  /**
    * Create accessible tree.
    *
    * @param aRoot       [in] a root of subtree to create
    * @param aFocusedAcc [in, optional] a focused accessible under created
    *                      subtree if any
    */
   void CacheChildrenInSubtree(Accessible* aRoot,
                               Accessible** aFocusedAcc = nullptr);
@@ -642,16 +663,35 @@ protected:
    * Used for our caching algorithm. We store the list of nodes that should be
    * invalidated.
    *
    * @see ProcessInvalidationList
    */
   nsTArray<nsIContent*> mInvalidationList;
 
   /**
+   * Holds a list of aria-owns relations.
+   */
+  nsClassHashtable<nsPtrHashKey<Accessible>, nsTArray<nsIContent*> >
+    mARIAOwnsHash;
+
+  struct ARIAOwnsPair {
+    ARIAOwnsPair(Accessible* aOwner, nsIContent* aChild) :
+      mOwner(aOwner), mChild(aChild) { }
+    ARIAOwnsPair(const ARIAOwnsPair& aPair) :
+      mOwner(aPair.mOwner), mChild(aPair.mChild) { }
+    ARIAOwnsPair& operator =(const ARIAOwnsPair& aPair)
+      { mOwner = aPair.mOwner; mChild = aPair.mChild; return *this; }
+
+    Accessible* mOwner;
+    nsIContent* mChild;
+  };
+  nsTArray<ARIAOwnsPair> mARIAOwnsInvalidationList;
+
+  /**
    * Used to process notification from core and accessible events.
    */
   nsRefPtr<NotificationController> mNotificationController;
   friend class EventQueue;
   friend class NotificationController;
 
 private:
 
--- a/accessible/tests/mochitest/common.js
+++ b/accessible/tests/mochitest/common.js
@@ -447,36 +447,49 @@ function testAccessibleTree(aAccOrElmOrI
     }
   }
 
   // Test children.
   if ("children" in accTree && accTree["children"] instanceof Array) {
     var children = acc.children;
     var childCount = children.length;
 
-
     if (accTree.children.length != childCount) {
       for (var i = 0; i < Math.max(accTree.children.length, childCount); i++) {
         var accChild;
         try {
           accChild = children.queryElementAt(i, nsIAccessible);
-          if (!accTree.children[i]) {
+
+          testChild = accTree.children[i];
+          if (!testChild) {
             ok(false, prettyName(acc) + " has an extra child at index " + i +
               " : " + prettyName(accChild));
+            continue;
           }
-          if (accChild.role !== accTree.children[i].role) {
+
+          var key = Object.keys(testChild)[0];
+          var roleName = "ROLE_" + key;
+          if (roleName in nsIAccessibleRole) {
+            testChild = {
+              role: nsIAccessibleRole[roleName],
+              children: testChild[key]
+            };
+          }
+
+          if (accChild.role !== testChild.role) {
             ok(false, prettyName(accTree) + " and " + prettyName(acc) +
               " have different children at index " + i + " : " +
-              prettyName(accTree.children[i]) + ", " + prettyName(accChild));
+              prettyName(testChild) + ", " + prettyName(accChild));
           }
           info("Matching " + prettyName(accTree) + " and " + prettyName(acc) +
                " child at index " + i + " : " + prettyName(accChild));
         } catch (e) {
           ok(false, prettyName(accTree) + " has an extra child at index " + i +
-             " : " + prettyName(accTree.children[i]));
+             " : " + prettyName(testChild) + ", " + e);
+          throw e;
         }
       }
     } else {
       if (aFlags & kSkipTreeFullCheck) {
         for (var i = 0; i < childCount; i++) {
           var child = children.queryElementAt(i, nsIAccessible);
           testAccessibleTree(child, accTree.children[i], aFlags);
         }
--- a/accessible/tests/mochitest/tree/test_aria_presentation.html
+++ b/accessible/tests/mochitest/tree/test_aria_presentation.html
@@ -82,29 +82,26 @@
       ] };
     testAccessibleTree("list_cnt", tree);
 
     // Has ARIA globals or referred by ARIA relationship, role='presentation'
     // and role='none' are ignored.
     tree =
       { SECTION: [ // container
         { LABEL: [ // label, has aria-owns
-          { TEXT_LEAF: [ ] }
-        ] },
-        { TEXT_LEAF: [ ] },
-        { LABEL: [ // label, referenced by aria-owns
-          { TEXT_LEAF: [ ] }
+          { TEXT_LEAF: [ ] },
+          { LABEL: [ // label, referenced by aria-owns
+            { TEXT_LEAF: [ ] }
+          ] },
         ] },
-        { TEXT_LEAF: [ ] },
         { LABEL: [ // label, has aria-owns
-          { TEXT_LEAF: [ ] }
-        ] },
-        { TEXT_LEAF: [ ] },
-        { LABEL: [ // label, referenced by aria-owns
-          { TEXT_LEAF: [ ] }
+          { TEXT_LEAF: [ ] },
+          { LABEL: [ // label, referenced by aria-owns
+            { TEXT_LEAF: [ ] }
+          ] }
         ] }
       ] };
     testAccessibleTree("airaglobalprop_cnt", tree);
 
     SimpleTest.finish();
   }
 
   SimpleTest.waitForExplicitFinish();
@@ -167,17 +164,16 @@
     <ul role="presentation">
       <li>item</li>
     </ul>
     <ul role="none">
       <li>item</li>
     </ul>
   </div>
 
-  <div id="airaglobalprop_cnt">
-    <label role="presentation" aria-owns="ariaowned">has aria-owns</label>
-    <label role="presentation" id="ariaowned">referred by aria-owns</label>
-    <label role="none" aria-owns="ariaowned2">has aria-owns</label>
-    <label role="none" id="ariaowned2">referred by aria-owns</label>
-  </div>
+  <div id="airaglobalprop_cnt"><label
+    role="presentation" aria-owns="ariaowned">has aria-owns</label><label
+    role="presentation" id="ariaowned">referred by aria-owns</label><label
+    role="none" aria-owns="ariaowned2">has aria-owns</label><label
+    role="none" id="ariaowned2">referred by aria-owns</label></div>
 
 </body>
 </html>
--- a/accessible/tests/mochitest/treeupdate/a11y.ini
+++ b/accessible/tests/mochitest/treeupdate/a11y.ini
@@ -1,11 +1,12 @@
 [DEFAULT]
 
 [test_ariadialog.html]
+[test_ariaowns.html]
 [test_bug852150.xhtml]
 [test_bug883708.xhtml]
 [test_bug884251.xhtml]
 [test_bug895082.html]
 [test_bug1040735.html]
 [test_bug1100602.html]
 [test_bug1175913.html]
 [test_bug1189277.html]
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/treeupdate/test_ariaowns.html
@@ -0,0 +1,234 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+  <title>@aria-owns attribute testing</title>
+
+  <link rel="stylesheet" type="text/css"
+        href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+  <script type="application/javascript"
+          src="../common.js"></script>
+  <script type="application/javascript"
+          src="../role.js"></script>
+  <script type="application/javascript"
+          src="../events.js"></script>
+
+  <script type="application/javascript">
+
+    ////////////////////////////////////////////////////////////////////////////
+    // Invokers
+    ////////////////////////////////////////////////////////////////////////////
+
+    function removeARIAOwns()
+    {
+      this.eventSeq = [
+        new invokerChecker(EVENT_HIDE, getNode("t2_checkbox")),
+        new invokerChecker(EVENT_HIDE, getNode("t2_button")),
+        new invokerChecker(EVENT_SHOW, getNode("t2_button")),
+        new invokerChecker(EVENT_SHOW, getNode("t2_checkbox")),
+        new invokerChecker(EVENT_REORDER, getNode("container2"))
+      ];
+
+      this.invoke = function removeARIAOwns_invoke()
+      {
+        // children are swapped
+        var tree =
+          { SECTION: [
+              { CHECKBUTTON: [
+                { SECTION: [] }
+              ] },
+              { PUSHBUTTON: [ ] }
+          ] };
+        testAccessibleTree("container2", tree);
+
+        getNode("container2").removeAttribute("aria-owns");
+      }
+
+      this.finalCheck = function removeARIAOwns_finalCheck()
+      {
+        // children follow the DOM order
+        var tree =
+          { SECTION: [
+              { PUSHBUTTON: [ ] },
+              { CHECKBUTTON: [
+                  { SECTION: [] }
+              ] }
+          ] };
+        testAccessibleTree("container2", tree);
+      }
+
+      this.getID = function removeARIAOwns_getID()
+      {
+        return "Remove @aria-owns attribute";
+      }
+    }
+
+    function setARIAOwns()
+    {
+      this.eventSeq = [
+        new invokerChecker(EVENT_HIDE, getNode("t2_button")),
+        new invokerChecker(EVENT_SHOW, getNode("t2_button")),
+        new invokerChecker(EVENT_HIDE, getNode("t2_subdiv")),
+        new invokerChecker(EVENT_SHOW, getNode("t2_subdiv")),
+        new invokerChecker(EVENT_REORDER, getNode("container2"))
+      ];
+
+      this.invoke = function setARIAOwns_invoke()
+      {
+        getNode("container2").setAttribute("aria-owns", "t2_button t2_subdiv");
+      }
+
+      this.finalCheck = function setARIAOwns_finalCheck()
+      {
+        // children are swapped again, button and subdiv are appended to
+        // the children.
+        var tree =
+          { SECTION: [
+              { CHECKBUTTON: [ ] }, // div
+              { PUSHBUTTON: [ ] }, // button
+              { SECTION: [ ] } // subdiv
+          ] };
+        testAccessibleTree("container2", tree);
+      }
+
+      this.getID = function setARIAOwns_getID()
+      {
+        return "Set @aria-owns attribute";
+      }
+    }
+
+    function appendEl()
+    {
+      this.eventSeq = [
+        new invokerChecker(EVENT_SHOW, getNode, "child3"),
+        new invokerChecker(EVENT_REORDER, getNode("container2"))
+      ];
+
+      this.invoke = function appendEl_invoke()
+      {
+        var div = document.createElement("div");
+        div.setAttribute("id", "child3");
+        div.setAttribute("role", "radio")
+        getNode("container2").appendChild(div);
+      }
+
+      this.finalCheck = function appendEl_finalCheck()
+      {
+        // children are invalidated, they includes aria-owns swapped kids and
+        // newly inserted child.
+        var tree =
+          { SECTION: [
+              { CHECKBUTTON: [ ] },
+              { RADIOBUTTON: [ ] },
+              { PUSHBUTTON: [ ] }, // ARIA owned
+              { SECTION: [ ] } // ARIA owned
+          ] };
+        testAccessibleTree("container2", tree);
+      }
+
+      this.getID = function appendEl_getID()
+      {
+        return "Append child under @aria-owns element";
+      }
+    }
+
+    function removeEl()
+    {
+      this.eventSeq = [
+        new invokerChecker(EVENT_HIDE, getNode, "t2_checkbox"),
+        new invokerChecker(EVENT_SHOW, getNode, "t2_checkbox"),
+        new invokerChecker(EVENT_REORDER, getNode("container2"))
+      ];
+
+      this.invoke = function removeEl_invoke()
+      {
+        // remove a container of t2_subdiv
+        getNode("t2_span").parentNode.removeChild(getNode("t2_span"));
+      }
+
+      this.finalCheck = function removeEl_finalCheck()
+      {
+        // subdiv should go away
+        var tree =
+          { SECTION: [
+              { CHECKBUTTON: [ ] },
+              { RADIOBUTTON: [ ] },
+              { PUSHBUTTON: [ ] } // ARIA owned
+          ] };
+        testAccessibleTree("container2", tree);
+      }
+
+      this.getID = function removeEl_getID()
+      {
+        return "Remove a container of ARIA ownded element";
+      }
+    }
+
+    ////////////////////////////////////////////////////////////////////////////
+    // Test
+    ////////////////////////////////////////////////////////////////////////////
+
+    gA11yEventDumpToConsole = true;
+    enableLogging("tree"); // debug stuff
+
+    var gQueue = null;
+
+    function doTest()
+    {
+      // nested and recursive aria-owns
+      var tree =
+        { SECTION: [ // container
+          { SECTION: [ // child
+            { SECTION: [ // mid div
+              { SECTION: [] } // grandchild
+            ] }
+          ] }
+        ] };
+      testAccessibleTree("container", tree);
+
+      // dynamic tests
+      gQueue = new eventQueue();
+
+      gQueue.push(new removeARIAOwns());
+      gQueue.push(new setARIAOwns());
+      gQueue.push(new appendEl());
+      gQueue.push(new removeEl());
+
+      gQueue.invoke(); // SimpleTest.finish() will be called in the end
+    }
+
+    SimpleTest.waitForExplicitFinish();
+    addA11yLoadEvent(doTest);
+
+  </script>
+</head>
+
+<body>
+
+  <p id="display"></p>
+  <div id="content" style="display: none"></div>
+  <pre id="test">
+  </pre>
+
+  <div id="container" aria-owns="child" aria-label="container"></div>
+  <div id="child" aria-label="child">
+    <div aria-owns="grandchild" aria-label="midchild"></div>
+  </div>
+  <div id="grandchild" aria-owns="container" aria-label="grandchild"></div>
+
+  <div id="container2" aria-owns="t2_checkbox t2_button">
+    <div role="button" id="t2_button"></div>
+    <div role="checkbox" id="t2_checkbox">
+      <span id="t2_span">
+        <div id="t2_subdiv"></div>
+      </span>
+    </div>
+  </div>
+
+</body>
+
+</html>
--- a/build/upload.py
+++ b/build/upload.py
@@ -10,16 +10,20 @@
 # UPLOAD_USER    : username on that host
 #  and one of the following:
 # UPLOAD_PATH    : path on that host to put the files in
 # UPLOAD_TO_TEMP : upload files to a new temporary directory
 #
 # If UPLOAD_HOST and UPLOAD_USER are not set, this script will simply write out
 # the properties file.
 #
+# If UPLOAD_HOST is "localhost", then files are simply copied to UPLOAD_PATH.
+# In this case, UPLOAD_TO_TEMP and POST_UPLOAD_CMD are not supported, and no
+# properties are written out.
+#
 # And will use the following optional environment variables if set:
 # UPLOAD_SSH_KEY : path to a ssh private key to use
 # UPLOAD_PORT    : port to use for ssh
 # POST_UPLOAD_CMD: a commandline to run on the remote host after uploading.
 #                  UPLOAD_PATH and the full paths of all files uploaded will
 #                  be appended to the commandline.
 #
 # All files to be uploaded should be passed as commandline arguments to this
@@ -27,16 +31,17 @@
 # to indicate that files should be uploaded including their paths relative
 # to the base path.
 
 import sys, os
 import re
 import json
 import errno
 import hashlib
+import shutil
 from optparse import OptionParser
 from subprocess import check_call, check_output, STDOUT
 import redo
 
 def OptionalEnvironmentVariable(v):
     """Return the value of the environment variable named v, or None
     if it's unset (or empty)."""
     if v in os.environ and os.environ[v] != "":
@@ -101,17 +106,17 @@ def DoSCPFile(file, remote_path, user, h
     cmdline.extend([WindowsPathToMsysPath(file),
                     "%s@%s:%s" % (user, host, remote_path)])
     with redo.retrying(check_call, sleeptime=10) as f:
         f(cmdline)
         return
 
     raise Exception("Command %s returned non-zero exit code" % cmdline)
 
-def GetRemotePath(path, local_file, base_path):
+def GetBaseRelativePath(path, local_file, base_path):
     """Given a remote path to upload to, a full path to a local file, and an
     optional full path that is a base path of the local file, construct the
     full remote path to place the file in. If base_path is not None, include
     the relative path from base_path to file."""
     if base_path is None or not local_file.startswith(base_path):
         return path
     dir = os.path.dirname(local_file)
     # strip base_path + extra slash and make it unixy
@@ -209,17 +214,17 @@ def UploadFiles(user, host, path, files,
     remote_files = []
     properties = {}
     try:
         for file in files:
             file = os.path.abspath(file)
             if not os.path.isfile(file):
                 raise IOError("File not found: %s" % file)
             # first ensure that path exists remotely
-            remote_path = GetRemotePath(path, file, base_path)
+            remote_path = GetBaseRelativePath(path, file, base_path)
             DoSSHCommand("mkdir -p " + remote_path, user, host, port=port, ssh_key=ssh_key)
             if verbose:
                 print "Uploading " + file
             DoSCPFile(file, remote_path, user, host, port=port, ssh_key=ssh_key)
             remote_files.append(remote_path + '/' + os.path.basename(file))
         if post_upload_command is not None:
             if verbose:
                 print "Running post-upload command: " + post_upload_command
@@ -231,16 +236,35 @@ def UploadFiles(user, host, path, files,
     finally:
         if upload_to_temp_dir:
             DoSSHCommand("rm -rf %s" % path, user, host, port=port,
                          ssh_key=ssh_key)
     if verbose:
         print "Upload complete"
     return properties
 
+def CopyFilesLocally(path, files, verbose=False, base_path=None, package=None):
+    """Copy each file in the list of files to `path`.  The `base_path` argument is treated
+    as it is by UploadFiles."""
+    if not path.endswith("/"):
+        path += "/"
+    if base_path is not None:
+        base_path = os.path.abspath(base_path)
+    for file in files:
+        file = os.path.abspath(file)
+        if not os.path.isfile(file):
+            raise IOError("File not found: %s" % file)
+        # first ensure that path exists remotely
+        target_path = GetBaseRelativePath(path, file, base_path)
+        if not os.path.exists(target_path):
+            os.makedirs(target_path)
+        if verbose:
+            print "Copying " + file + " to " + target_path
+        shutil.copy(file, target_path)
+
 def WriteProperties(files, properties_file, url_properties, package):
     properties = url_properties
     for file in files:
         if file.endswith('.complete.mar'):
             properties.update(GetMarProperties(file))
     with open(properties_file, 'w') as outfile:
         properties['packageFilename'] = package
         properties['uploadFiles'] = [os.path.abspath(f) for f in files]
@@ -275,21 +299,35 @@ if __name__ == '__main__':
                       help="Name of the main package.")
     (options, args) = parser.parse_args()
     if len(args) < 1:
         print "You must specify at least one file to upload"
         sys.exit(1)
     if not options.properties_file:
         print "You must specify a --properties-file"
         sys.exit(1)
+
+    if host == "localhost":
+        if upload_to_temp_dir:
+            print "Cannot use UPLOAD_TO_TEMP with UPLOAD_HOST=localhost"
+            sys.exit(1)
+        if post_upload_command:
+            # POST_UPLOAD_COMMAND is difficult to extract from the mozharness
+            # scripts, so just ignore it until it's no longer used anywhere
+            print "Ignoring POST_UPLOAD_COMMAND with UPLOAD_HOST=localhost"
+
     try:
-        url_properties = UploadFiles(user, host, path, args, base_path=options.base_path,
-                                     port=port, ssh_key=key, upload_to_temp_dir=upload_to_temp_dir,
-                                     post_upload_command=post_upload_command,
-                                     package=options.package,
-                                     verbose=True)
-        WriteProperties(args, options.properties_file, url_properties, options.package)
+        if host == "localhost":
+            CopyFilesLocally(path, args, base_path=options.base_path,
+                             package=options.package,
+                             verbose=True)
+        else:
+
+            url_properties = UploadFiles(user, host, path, args,
+                                         base_path=options.base_path, port=port, ssh_key=key,
+                                         upload_to_temp_dir=upload_to_temp_dir,
+                                         post_upload_command=post_upload_command,
+                                         package=options.package, verbose=True)
+
+            WriteProperties(args, options.properties_file, url_properties, options.package)
     except IOError, (strerror):
         print strerror
         sys.exit(1)
-    except Exception, (err):
-        print err
-        sys.exit(2)
--- a/dom/base/ChildIterator.h
+++ b/dom/base/ChildIterator.h
@@ -195,16 +195,17 @@ public:
 #endif
       {}
 
 #ifdef DEBUG
   ~AllChildrenIterator() { MOZ_ASSERT(!mMutationGuard.Mutated(0)); }
 #endif
 
   nsIContent* GetNextChild();
+  nsIContent* Parent() const { return mOriginalContent; }
 
 private:
   enum IteratorPhase
   {
     eNeedBeforeKid,
     eNeedExplicitKids,
     eNeedAnonKids,
     eNeedAfterKid,
--- a/dom/media/MediaDecoderStateMachine.cpp
+++ b/dom/media/MediaDecoderStateMachine.cpp
@@ -131,17 +131,17 @@ static const int64_t LOW_DATA_THRESHOLD_
 // LOW_DATA_THRESHOLD_USECS needs to be greater than AMPLE_AUDIO_USECS, otherwise
 // the skip-to-keyframe logic can activate when we're running low on data.
 static_assert(LOW_DATA_THRESHOLD_USECS > AMPLE_AUDIO_USECS,
               "LOW_DATA_THRESHOLD_USECS is too small");
 
 } // namespace detail
 
 // Amount of excess usecs of data to add in to the "should we buffer" calculation.
-static const uint32_t EXHAUSTED_DATA_MARGIN_USECS = 60000;
+static const uint32_t EXHAUSTED_DATA_MARGIN_USECS = 100000;
 
 // If we enter buffering within QUICK_BUFFER_THRESHOLD_USECS seconds of starting
 // decoding, we'll enter "quick buffering" mode, which exits a lot sooner than
 // normal buffering mode. This exists so that if the decode-ahead exhausts the
 // downloaded data while decode/playback is just starting up (for example
 // after a seek while the media is still playing, or when playing a media
 // as soon as it's load started), we won't necessarily stop for 30s and wait
 // for buffering. We may actually be able to playback in this case, so exit
@@ -694,26 +694,28 @@ MediaDecoderStateMachine::PushFront(Medi
 void
 MediaDecoderStateMachine::OnAudioPopped(const nsRefPtr<MediaData>& aSample)
 {
   MOZ_ASSERT(OnTaskQueue());
   ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
   mPlaybackOffset = std::max(mPlaybackOffset.Ref(), aSample->mOffset);
   UpdateNextFrameStatus();
   DispatchAudioDecodeTaskIfNeeded();
+  MaybeStartBuffering();
 }
 
 void
 MediaDecoderStateMachine::OnVideoPopped(const nsRefPtr<MediaData>& aSample)
 {
   MOZ_ASSERT(OnTaskQueue());
   ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
   mPlaybackOffset = std::max(mPlaybackOffset.Ref(), aSample->mOffset);
   UpdateNextFrameStatus();
   DispatchVideoDecodeTaskIfNeeded();
+  MaybeStartBuffering();
 }
 
 void
 MediaDecoderStateMachine::OnNotDecoded(MediaData::Type aType,
                                        MediaDecoderReader::NotDecodedReason aReason)
 {
   MOZ_ASSERT(OnTaskQueue());
   ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
@@ -1092,16 +1094,44 @@ void MediaDecoderStateMachine::MaybeStar
   if (!IsPlaying()) {
     mMediaSink->SetPlaying(true);
     MOZ_ASSERT(IsPlaying());
   }
 
   DispatchDecodeTasksIfNeeded();
 }
 
+void
+MediaDecoderStateMachine::MaybeStartBuffering()
+{
+  MOZ_ASSERT(OnTaskQueue());
+  AssertCurrentThreadInMonitor();
+
+  if (mState == DECODER_STATE_DECODING &&
+      mPlayState == MediaDecoder::PLAY_STATE_PLAYING &&
+      mResource->IsExpectingMoreData()) {
+    bool shouldBuffer;
+    if (mReader->UseBufferingHeuristics()) {
+      shouldBuffer = HasLowDecodedData(EXHAUSTED_DATA_MARGIN_USECS) &&
+                     (JustExitedQuickBuffering() || HasLowUndecodedData());
+    } else {
+      MOZ_ASSERT(mReader->IsWaitForDataSupported());
+      shouldBuffer = (OutOfDecodedAudio() && mAudioWaitRequest.Exists()) ||
+                     (OutOfDecodedVideo() && mVideoWaitRequest.Exists());
+    }
+    if (shouldBuffer) {
+      StartBuffering();
+      // Don't go straight back to the state machine loop since that might
+      // cause us to start decoding again and we could flip-flop between
+      // decoding and quick-buffering.
+      ScheduleStateMachineIn(USECS_PER_S);
+    }
+  }
+}
+
 void MediaDecoderStateMachine::UpdatePlaybackPositionInternal(int64_t aTime)
 {
   MOZ_ASSERT(OnTaskQueue());
   SAMPLE_LOG("UpdatePlaybackPositionInternal(%lld)", aTime);
   AssertCurrentThreadInMonitor();
 
   mCurrentPosition = aTime;
   NS_ASSERTION(mCurrentPosition >= 0, "CurrentTime should be positive!");
@@ -2607,40 +2637,16 @@ void MediaDecoderStateMachine::UpdateRen
       mVideoFrameEndTime = currentFrame->GetEndTime();
       MediaDecoder::FrameStatistics& frameStats = mDecoder->GetFrameStatistics();
       frameStats.NotifyPresentedFrame();
     }
   }
 
   RenderVideoFrames(sVideoQueueSendToCompositorSize, clockTime, nowTime);
 
-  // Check to see if we don't have enough data to play up to the next frame.
-  // If we don't, switch to buffering mode.
-  if (mState == DECODER_STATE_DECODING &&
-      mPlayState == MediaDecoder::PLAY_STATE_PLAYING &&
-      mResource->IsExpectingMoreData()) {
-    bool shouldBuffer;
-    if (mReader->UseBufferingHeuristics()) {
-      shouldBuffer = HasLowDecodedData(remainingTime + EXHAUSTED_DATA_MARGIN_USECS) &&
-                     (JustExitedQuickBuffering() || HasLowUndecodedData());
-    } else {
-      MOZ_ASSERT(mReader->IsWaitForDataSupported());
-      shouldBuffer = (OutOfDecodedAudio() && mAudioWaitRequest.Exists()) ||
-                     (OutOfDecodedVideo() && mVideoWaitRequest.Exists());
-    }
-    if (shouldBuffer) {
-      StartBuffering();
-      // Don't go straight back to the state machine loop since that might
-      // cause us to start decoding again and we could flip-flop between
-      // decoding and quick-buffering.
-      ScheduleStateMachineIn(USECS_PER_S);
-      return;
-    }
-  }
-
   // Cap the current time to the larger of the audio and video end time.
   // This ensures that if we're running off the system clock, we don't
   // advance the clock to after the media end time.
   if (mVideoFrameEndTime != -1 || AudioEndTime() != -1) {
     // These will be non -1 if we've displayed a video frame, or played an audio frame.
     int64_t t = std::min(clockTime, std::max(mVideoFrameEndTime, AudioEndTime()));
     // FIXME: Bug 1091422 - chained ogg files hit this assertion.
     //MOZ_ASSERT(t >= GetMediaTime());
--- a/dom/media/MediaDecoderStateMachine.h
+++ b/dom/media/MediaDecoderStateMachine.h
@@ -517,16 +517,20 @@ protected:
   // The decoder monitor must be held.
   void StopPlayback();
 
   // If the conditions are right, sets internal state which causes playback
   // of media to begin or resume.
   // Must be called with the decode monitor held.
   void MaybeStartPlayback();
 
+  // Check to see if we don't have enough data to play up to the next frame.
+  // If we don't, switch to buffering mode.
+  void MaybeStartBuffering();
+
   // Moves the decoder into decoding state. Called on the state machine
   // thread. The decoder monitor must be held.
   void StartDecoding();
 
   // Moves the decoder into the shutdown state, and dispatches an error
   // event to the media element. This begins shutting down the decoder.
   // The decoder monitor must be held. This is only called on the
   // decode thread.
--- a/dom/tests/mochitest/fetch/mochitest.ini
+++ b/dom/tests/mochitest/fetch/mochitest.ini
@@ -22,20 +22,20 @@ support-files =
 skip-if = buildapp == 'b2g' # Bug 1137683
 [test_headers_mainthread.html]
 [test_fetch_app_protocol.html]
 [test_fetch_basic.html]
 [test_fetch_basic_sw_reroute.html]
 skip-if = buildapp == 'b2g' # Bug 1137683
 [test_fetch_basic_http.html]
 [test_fetch_basic_http_sw_reroute.html]
-skip-if = e10s || buildapp == 'b2g' || buildapp == 'mulet' # Bug 1093357 for e10s, bug 1137683 for b2g, bug 1174872 for mulet
+skip-if = buildapp == 'b2g' || buildapp == 'mulet' # Bug 1137683 for b2g, bug 1174872 for mulet
 [test_fetch_cors.html]
 [test_fetch_cors_sw_reroute.html]
-skip-if = e10s || buildapp == 'b2g' # Bug 1093357 for e10s, bug 1137683 for b2g
+skip-if = buildapp == 'b2g' # Bug 1137683 for b2g
 [test_formdataparsing.html]
 [test_formdataparsing_sw_reroute.html]
 skip-if = buildapp == 'b2g' # Bug 1137683
 [test_request.html]
 [test_request_context.html]
 [test_request_sw_reroute.html]
 skip-if = buildapp == 'b2g' # Bug 1137683
 [test_response.html]
--- a/dom/workers/ServiceWorkerManager.cpp
+++ b/dom/workers/ServiceWorkerManager.cpp
@@ -3862,16 +3862,92 @@ private:
       }
 
       MOZ_ALWAYS_TRUE(NS_SUCCEEDED(NS_DispatchToMainThread(runnable)));
     }
     return true;
   }
 };
 
+namespace {
+
+class ContinueDispatchFetchEventRunnable : public nsRunnable
+{
+  WorkerPrivate* mWorkerPrivate;
+  nsMainThreadPtrHandle<nsIInterceptedChannel> mChannel;
+  nsMainThreadPtrHandle<ServiceWorker> mServiceWorker;
+  nsAutoPtr<ServiceWorkerClientInfo> mClientInfo;
+  bool mIsReload;
+public:
+  ContinueDispatchFetchEventRunnable(WorkerPrivate* aWorkerPrivate,
+                                     nsMainThreadPtrHandle<nsIInterceptedChannel>& aChannel,
+                                     nsMainThreadPtrHandle<ServiceWorker>& aServiceWorker,
+                                     nsAutoPtr<ServiceWorkerClientInfo>& aClientInfo,
+                                     bool aIsReload)
+    : mWorkerPrivate(aWorkerPrivate)
+    , mChannel(aChannel)
+    , mServiceWorker(aServiceWorker)
+    , mClientInfo(aClientInfo)
+    , mIsReload(aIsReload)
+  {
+  }
+
+  void
+  HandleError()
+  {
+    MOZ_ASSERT(NS_IsMainThread());
+    NS_WARNING("Unexpected error while dispatching fetch event!");
+    DebugOnly<nsresult> rv = mChannel->ResetInterception();
+    NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Failed to resume intercepted network request");
+  }
+
+  NS_IMETHOD
+  Run() override
+  {
+    MOZ_ASSERT(NS_IsMainThread());
+
+    nsCOMPtr<nsIChannel> channel;
+    nsresult rv = mChannel->GetChannel(getter_AddRefs(channel));
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      HandleError();
+      return NS_OK;
+    }
+
+    // The channel might have encountered an unexpected error while ensuring
+    // the upload stream is cloneable.  Check here and reset the interception
+    // if that happens.
+    nsresult status;
+    rv = channel->GetStatus(&status);
+    if (NS_WARN_IF(NS_FAILED(rv) || NS_FAILED(status))) {
+      HandleError();
+      return NS_OK;
+    }
+
+    nsRefPtr<FetchEventRunnable> event =
+      new FetchEventRunnable(mWorkerPrivate, mChannel, mServiceWorker,
+                             mClientInfo, mIsReload);
+    rv = event->Init();
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      HandleError();
+      return NS_OK;
+    }
+
+    AutoJSAPI jsapi;
+    jsapi.Init();
+    if (NS_WARN_IF(!event->Dispatch(jsapi.cx()))) {
+      HandleError();
+      return NS_OK;
+    }
+
+    return NS_OK;
+  }
+};
+
+} // anonymous namespace
+
 NS_IMPL_ISUPPORTS_INHERITED(FetchEventRunnable, WorkerRunnable, nsIHttpHeaderVisitor)
 
 void
 ServiceWorkerManager::DispatchFetchEvent(const OriginAttributes& aOriginAttributes,
                                          nsIDocument* aDoc,
                                          nsIInterceptedChannel* aChannel,
                                          bool aIsReload,
                                          ErrorResult& aRv)
@@ -3935,31 +4011,38 @@ ServiceWorkerManager::DispatchFetchEvent
 
   nsMainThreadPtrHandle<nsIInterceptedChannel> handle(
     new nsMainThreadPtrHolder<nsIInterceptedChannel>(aChannel, false));
 
   nsRefPtr<ServiceWorker> sw = static_cast<ServiceWorker*>(serviceWorker.get());
   nsMainThreadPtrHandle<ServiceWorker> serviceWorkerHandle(
     new nsMainThreadPtrHolder<ServiceWorker>(sw));
 
-  // clientInfo is null if we don't have a controlled document
-  nsRefPtr<FetchEventRunnable> event =
-    new FetchEventRunnable(sw->GetWorkerPrivate(), handle, serviceWorkerHandle,
-                           clientInfo, aIsReload);
-  aRv = event->Init();
+  nsCOMPtr<nsIRunnable> continueRunnable =
+    new ContinueDispatchFetchEventRunnable(sw->GetWorkerPrivate(), handle,
+                                           serviceWorkerHandle, clientInfo,
+                                           aIsReload);
+
+  nsCOMPtr<nsIChannel> innerChannel;
+  aRv = aChannel->GetChannel(getter_AddRefs(innerChannel));
   if (NS_WARN_IF(aRv.Failed())) {
     return;
   }
 
-  AutoJSAPI api;
-  api.Init();
-  if (NS_WARN_IF(!event->Dispatch(api.cx()))) {
-    aRv.Throw(NS_ERROR_FAILURE);
+  nsCOMPtr<nsIUploadChannel2> uploadChannel = do_QueryInterface(innerChannel);
+
+  // If there is no upload stream, then continue immediately
+  if (!uploadChannel) {
+    MOZ_ALWAYS_TRUE(NS_SUCCEEDED(continueRunnable->Run()));
     return;
   }
+
+  // Otherwise, ensure the upload stream can be cloned directly.  This may
+  // require some async copying, so provide a callback.
+  aRv = uploadChannel->EnsureUploadStreamIsCloneable(continueRunnable);
 }
 
 bool
 ServiceWorkerManager::IsAvailable(const OriginAttributes& aOriginAttributes,
                                   nsIURI* aURI)
 {
   MOZ_ASSERT(aURI);
 
--- a/dom/workers/test/serviceworkers/mochitest.ini
+++ b/dom/workers/test/serviceworkers/mochitest.ini
@@ -155,16 +155,18 @@ support-files =
   opaque_intercept_worker.js
   notify_loaded.js
   test_request_context.js
   fetch_event_client.js
   sw_clients/dummy.html
   fetch/plugin/worker.js
   fetch/plugin/plugins.html
   eventsource/*
+  sw_clients/file_blob_upload_frame.html
+  redirect_post.sjs
 
 [test_app_protocol.html]
 skip-if = release_build
 [test_bug1151916.html]
 [test_claim.html]
 [test_claim_fetch.html]
 [test_claim_oninstall.html]
 [test_close.html]
@@ -246,8 +248,9 @@ skip-if = toolkit == "android" || toolki
 [test_workerUnregister.html]
 [test_workerUpdate.html]
 [test_workerupdatefoundevent.html]
 [test_opaque_intercept.html]
 [test_fetch_event_client_postmessage.html]
 [test_escapedSlashes.html]
 [test_eventsource_intercept.html]
 [test_not_intercept_plugin.html]
+[test_file_blob_upload.html]
new file mode 100644
--- /dev/null
+++ b/dom/workers/test/serviceworkers/redirect_post.sjs
@@ -0,0 +1,35 @@
+const CC = Components.Constructor;
+const BinaryInputStream = CC("@mozilla.org/binaryinputstream;1",
+                             "nsIBinaryInputStream",
+                             "setInputStream");
+
+function handleRequest(request, response)
+{
+  var query = {};
+  request.queryString.split('&').forEach(function (val) {
+    var [name, value] = val.split('=');
+    query[name] = unescape(value);
+  });
+
+  var bodyStream = new BinaryInputStream(request.bodyInputStream);
+  var bodyBytes = [];
+  while ((bodyAvail = bodyStream.available()) > 0)
+    Array.prototype.push.apply(bodyBytes, bodyStream.readByteArray(bodyAvail));
+
+  var body = decodeURIComponent(
+    escape(String.fromCharCode.apply(null, bodyBytes)));
+
+  var currentHop = query.hop ? parseInt(query.hop) : 0;
+
+  var obj = JSON.parse(body);
+  if (currentHop < obj.hops) {
+    var newURL = '/tests/dom/workers/test/serviceworkers/redirect_post.sjs?hop=' +
+                 (1 + currentHop);
+    response.setStatusLine(null, 307, 'redirect');
+    response.setHeader('Location', newURL);
+    return;
+  }
+
+  response.setHeader('Content-Type', 'application/json');
+  response.write(body);
+}
new file mode 100644
--- /dev/null
+++ b/dom/workers/test/serviceworkers/sw_clients/file_blob_upload_frame.html
@@ -0,0 +1,77 @@
+<!--
+  Any copyright is dedicated to the Public Domain.
+  http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>test file blob upload with SW interception</title>
+</head>
+<body>
+<p id="display"></p>
+<div id="content" style="display: none"></div>
+<pre id="test"></pre>
+<script class="testbody" type="text/javascript">
+
+if (!parent) {
+  dump("sw_clients/file_blob_upload_frame.html shouldn't be launched directly!");
+}
+
+function makeFileBlob(obj) {
+  return new Promise(function(resolve, reject) {
+
+    var request = indexedDB.open(window.location.pathname, 1);
+    request.onerror = reject;
+    request.onupgradeneeded = function(evt) {
+      var db = evt.target.result;
+      db.onerror = reject;
+
+      var objectStore = db.createObjectStore('test', { autoIncrement: true });
+      var index = objectStore.createIndex('test', 'index');
+    };
+
+    request.onsuccess = function(evt) {
+      var db = evt.target.result;
+      db.onerror = reject;
+
+      var blob = new Blob([JSON.stringify(obj)],
+                          { type: 'application/json' });
+      var data = { blob: blob, index: 5 };
+
+      objectStore = db.transaction('test', 'readwrite').objectStore('test');
+      objectStore.add(data).onsuccess = function(evt) {
+        var key = evt.target.result;
+        objectStore = db.transaction('test').objectStore('test');
+        objectStore.get(key).onsuccess = function(evt) {
+          resolve(evt.target.result.blob);
+        };
+      };
+    };
+  });
+}
+
+navigator.serviceWorker.ready.then(function() {
+  parent.postMessage({ status: 'READY' }, '*');
+});
+
+var URL = '/tests/dom/workers/test/serviceworkers/redirect_post.sjs';
+
+addEventListener('message', function(evt) {
+  if (evt.data.type = 'TEST') {
+    makeFileBlob(evt.data.body).then(function(blob) {
+      return fetch(URL, { method: 'POST', body: blob });
+    }).then(function(response) {
+      return response.json();
+    }).then(function(result) {
+      parent.postMessage({ status: 'OK', result: result }, '*');
+    }).catch(function(e) {
+      parent.postMessage({ status: 'ERROR', result: e.toString() }, '*');
+    });
+  }
+});
+
+</script>
+</pre>
+</body>
+</html>
+
new file mode 100644
--- /dev/null
+++ b/dom/workers/test/serviceworkers/test_file_blob_upload.html
@@ -0,0 +1,146 @@
+<!--
+  Any copyright is dedicated to the Public Domain.
+  http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Bug 1203680 - Test interception of file blob uploads</title>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<p id="display"></p>
+<div id="content" style="display: none"></div>
+<pre id="test"></pre>
+<script class="testbody" type="text/javascript">
+  var registration;
+  var iframe;
+  function start() {
+    return navigator.serviceWorker.register("empty.js",
+                                            { scope: "./sw_clients/" })
+      .then((swr) => registration = swr);
+  }
+
+  function unregister() {
+    if (iframe) {
+      iframe.remove();
+      iframe = null;
+    }
+
+    return registration.unregister().then(function(result) {
+      ok(result, "Unregister should return true.");
+    }, function(e) {
+      ok(false, "Unregistering the SW failed with " + e + "\n");
+    });
+  }
+
+  function withFrame() {
+    var content = document.getElementById("content");
+    ok(content, "Parent exists.");
+
+    iframe = document.createElement("iframe");
+    iframe.setAttribute('src', "sw_clients/file_blob_upload_frame.html");
+    content.appendChild(iframe);
+
+    return new Promise(function(resolve, reject) {
+      window.addEventListener('message', function readyCallback(evt) {
+        window.removeEventListener('message', readyCallback);
+        if (evt.data.status === 'READY') {
+          resolve();
+        } else {
+          reject(evt.data.result);
+        }
+      });
+    });
+  }
+
+  function postBlob(body) {
+    return new Promise(function(resolve, reject) {
+      window.addEventListener('message', function postBlobCallback(evt) {
+        window.removeEventListener('message', postBlobCallback);
+        if (evt.data.status === 'OK') {
+          is(JSON.stringify(body), JSON.stringify(evt.data.result),
+             'body echoed back correctly');
+          resolve();
+        } else {
+          reject(evt.data.result);
+        }
+      });
+
+      iframe.contentWindow.postMessage({ type: 'TEST', body: body }, '*');
+    });
+  }
+
+  function generateMessage(length) {
+
+    var lorem =
+      'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis egestas '
+      'vehicula tortor eget ultrices. Sed et luctus est. Nunc eu orci ligula. '
+      'In vel ornare eros, eget lacinia diam. Praesent vel metus mattis, '
+      'cursus nulla sit amet, rhoncus diam. Aliquam nulla tortor, aliquet et '
+      'viverra non, dignissim vel tellus. Praesent sed ex in dolor aliquet '
+      'aliquet. In at facilisis sem, et aliquet eros. Maecenas feugiat nisl '
+      'quis elit blandit posuere. Duis viverra odio sed eros consectetur, '
+      'viverra mattis ligula volutpat.';
+
+    var result = '';
+
+    while (result.length < length) {
+      var remaining = length - result.length;
+      if (remaining < lorem.length) {
+        result += lorem.slice(0, remaining);
+      } else {
+        result += lorem;
+      }
+    }
+
+    return result;
+  }
+
+  var smallBody = generateMessage(64);
+  var mediumBody = generateMessage(1024);
+
+  // TODO: Test large bodies over the default pipe size.  Currently stalls
+  //       due to bug 1134372.
+  //var largeBody = generateMessage(100 * 1024);
+
+  function runTest() {
+    start()
+      .then(withFrame)
+      .then(function() {
+        return postBlob({ hops: 0, message: smallBody });
+      })
+      .then(function() {
+        return postBlob({ hops: 1, message: smallBody });
+      })
+      .then(function() {
+        return postBlob({ hops: 10, message: smallBody });
+      })
+      .then(function() {
+        return postBlob({ hops: 0, message: mediumBody });
+      })
+      .then(function() {
+        return postBlob({ hops: 1, message: mediumBody });
+      })
+      .then(function() {
+        return postBlob({ hops: 10, message: mediumBody });
+      })
+      .then(unregister)
+      .catch(function(e) {
+        ok(false, "Some test failed with error " + e);
+      }).then(SimpleTest.finish);
+  }
+
+  SimpleTest.waitForExplicitFinish();
+  SpecialPowers.pushPrefEnv({"set": [
+    ["dom.serviceWorkers.exemptFromPerDomainMax", true],
+    ["dom.serviceWorkers.interception.enabled", true],
+    ["dom.serviceWorkers.enabled", true],
+    ["dom.serviceWorkers.testing.enabled", true]
+  ]}, runTest);
+</script>
+</pre>
+</body>
+</html>
+
--- a/gfx/layers/basic/BasicCompositor.cpp
+++ b/gfx/layers/basic/BasicCompositor.cpp
@@ -143,17 +143,17 @@ BasicCompositor::CreateDataTextureSource
 {
   RefPtr<DataTextureSource> result = new DataTextureSourceBasic();
   return result.forget();
 }
 
 bool
 BasicCompositor::SupportsEffect(EffectTypes aEffect)
 {
-  return static_cast<EffectTypes>(aEffect) != EffectTypes::YCBCR;
+  return aEffect != EffectTypes::YCBCR && aEffect != EffectTypes::COMPONENT_ALPHA;
 }
 
 static void
 DrawSurfaceWithTextureCoords(DrawTarget *aDest,
                              const gfx::Rect& aDestRect,
                              SourceSurface *aSource,
                              const gfx::Rect& aTextureCoords,
                              gfx::Filter aFilter,
--- a/gfx/layers/composite/ImageHost.cpp
+++ b/gfx/layers/composite/ImageHost.cpp
@@ -307,16 +307,20 @@ ImageHost::Composite(LayerComposite* aLa
     RefPtr<TexturedEffect> effect =
         CreateTexturedEffect(img->mFrontBuffer->GetFormat(),
             img->mTextureSource.get(), aFilter, isAlphaPremultiplied,
             GetRenderState());
     if (!effect) {
       return;
     }
 
+    if (!GetCompositor()->SupportsEffect(effect->mType)) {
+      return;
+    }
+
     if (mLastFrameID != img->mFrameID || mLastProducerID != img->mProducerID) {
       if (mImageContainer) {
         aLayer->GetLayerManager()->
             AppendImageCompositeNotification(ImageCompositeNotification(
                 mImageContainer, nullptr,
                 img->mTimeStamp, GetCompositor()->GetCompositionTime(),
                 img->mFrameID, img->mProducerID));
       }
--- a/gfx/layers/d3d11/CompositorD3D11.cpp
+++ b/gfx/layers/d3d11/CompositorD3D11.cpp
@@ -41,37 +41,47 @@ static const GUID sDeviceAttachmentsD3D1
 // {88041664-C835-4AA8-ACB8-7EC832357ED8}
 static const GUID sLayerManagerCount =
 { 0x88041664, 0xc835, 0x4aa8, { 0xac, 0xb8, 0x7e, 0xc8, 0x32, 0x35, 0x7e, 0xd8 } };
 
 const FLOAT sBlendFactor[] = { 0, 0, 0, 0 };
 
 struct DeviceAttachmentsD3D11
 {
+  DeviceAttachmentsD3D11(ID3D11Device* device)
+   : mDevice(device),
+     mInitOkay(true)
+  {}
+
+  bool CreateShaders();
+
   typedef EnumeratedArray<MaskType, MaskType::NumMaskTypes, RefPtr<ID3D11VertexShader>>
           VertexShaderArray;
   typedef EnumeratedArray<MaskType, MaskType::NumMaskTypes, RefPtr<ID3D11PixelShader>>
           PixelShaderArray;
 
   RefPtr<ID3D11InputLayout> mInputLayout;
   RefPtr<ID3D11Buffer> mVertexBuffer;
 
   VertexShaderArray mVSQuadShader;
   PixelShaderArray mSolidColorShader;
   PixelShaderArray mRGBAShader;
+  PixelShaderArray mRGBAShaderPremul;
   PixelShaderArray mRGBShader;
   PixelShaderArray mYCbCrShader;
   PixelShaderArray mComponentAlphaShader;
   RefPtr<ID3D11Buffer> mPSConstantBuffer;
   RefPtr<ID3D11Buffer> mVSConstantBuffer;
   RefPtr<ID3D11RasterizerState> mRasterizerState;
   RefPtr<ID3D11SamplerState> mLinearSamplerState;
   RefPtr<ID3D11SamplerState> mPointSamplerState;
   RefPtr<ID3D11BlendState> mPremulBlendState;
   RefPtr<ID3D11BlendState> mNonPremulBlendState;
+  RefPtr<ID3D11BlendState> mPremulBlendMultiplyState;
+  RefPtr<ID3D11BlendState> mPremulBlendScreenState;
   RefPtr<ID3D11BlendState> mComponentBlendState;
   RefPtr<ID3D11BlendState> mDisabledBlendState;
   RefPtr<IDXGIResource> mSyncTexture;
 
   //
   // VR pieces
   //
   typedef EnumeratedArray<VRHMDType, VRHMDType::NumHMDTypes, RefPtr<ID3D11InputLayout>>
@@ -88,16 +98,44 @@ struct DeviceAttachmentsD3D11
   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];
+
+private:
+  void InitVertexShader(const ShaderBytes& aShader, VertexShaderArray& aArray, MaskType aMaskType) {
+    InitVertexShader(aShader, byRef(aArray[aMaskType]));
+  }
+  void InitPixelShader(const ShaderBytes& aShader, PixelShaderArray& aArray, MaskType aMaskType) {
+    InitPixelShader(aShader, byRef(aArray[aMaskType]));
+  }
+  void InitVertexShader(const ShaderBytes& aShader, ID3D11VertexShader** aOut) {
+    if (!mInitOkay) {
+      return;
+    }
+    if (FAILED(mDevice->CreateVertexShader(aShader.mData, aShader.mLength, nullptr, aOut))) {
+      mInitOkay = false;
+    }
+  }
+  void InitPixelShader(const ShaderBytes& aShader, ID3D11PixelShader** aOut) {
+    if (!mInitOkay) {
+      return;
+    }
+    if (FAILED(mDevice->CreatePixelShader(aShader.mData, aShader.mLength, nullptr, aOut))) {
+      mInitOkay = false;
+    }
+  }
+
+  // Only used during initialization.
+  RefPtr<ID3D11Device> mDevice;
+  bool mInitOkay;
 };
 
 CompositorD3D11::CompositorD3D11(nsIWidget* aWidget)
   : mAttachments(nullptr)
   , mWidget(aWidget)
   , mHwnd(nullptr)
   , mDisableSequenceForNextFrame(false)
 {
@@ -166,17 +204,17 @@ CompositorD3D11::Initialize()
   mDevice->SetPrivateData(sLayerManagerCount,
                           sizeof(referenceCount),
                           &referenceCount);
 
   size = sizeof(DeviceAttachmentsD3D11*);
   if (FAILED(mDevice->GetPrivateData(sDeviceAttachmentsD3D11,
                                      &size,
                                      &mAttachments))) {
-    mAttachments = new DeviceAttachmentsD3D11;
+    mAttachments = new DeviceAttachmentsD3D11(mDevice);
     mDevice->SetPrivateData(sDeviceAttachmentsD3D11,
                             sizeof(mAttachments),
                             &mAttachments);
 
     D3D11_INPUT_ELEMENT_DESC layout[] =
     {
       { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
     };
@@ -197,17 +235,17 @@ CompositorD3D11::Initialize()
     data.pSysMem = (void*)vertices;
 
     hr = mDevice->CreateBuffer(&bufferDesc, &data, byRef(mAttachments->mVertexBuffer));
 
     if (FAILED(hr)) {
       return false;
     }
 
-    if (!CreateShaders()) {
+    if (!mAttachments->CreateShaders()) {
       return false;
     }
 
     CD3D11_BUFFER_DESC cBufferDesc(sizeof(VertexShaderConstants),
                                    D3D11_BIND_CONSTANT_BUFFER,
                                    D3D11_USAGE_DYNAMIC,
                                    D3D11_CPU_ACCESS_WRITE);
 
@@ -251,16 +289,40 @@ CompositorD3D11::Initialize()
       D3D11_COLOR_WRITE_ENABLE_ALL
     };
     blendDesc.RenderTarget[0] = rtBlendPremul;
     hr = mDevice->CreateBlendState(&blendDesc, byRef(mAttachments->mPremulBlendState));
     if (FAILED(hr)) {
       return false;
     }
 
+    D3D11_RENDER_TARGET_BLEND_DESC rtBlendMultiplyPremul = {
+      TRUE,
+      D3D11_BLEND_DEST_COLOR, D3D11_BLEND_INV_SRC_ALPHA, D3D11_BLEND_OP_ADD,
+      D3D11_BLEND_ONE, D3D11_BLEND_INV_SRC_ALPHA, D3D11_BLEND_OP_ADD,
+      D3D11_COLOR_WRITE_ENABLE_ALL
+    };
+    blendDesc.RenderTarget[0] = rtBlendMultiplyPremul;
+    hr = mDevice->CreateBlendState(&blendDesc, byRef(mAttachments->mPremulBlendMultiplyState));
+    if (FAILED(hr)) {
+      return false;
+    }
+
+    D3D11_RENDER_TARGET_BLEND_DESC rtBlendScreenPremul = {
+      TRUE,
+      D3D11_BLEND_ONE, D3D11_BLEND_INV_SRC_COLOR, D3D11_BLEND_OP_ADD,
+      D3D11_BLEND_ONE, D3D11_BLEND_INV_SRC_ALPHA, D3D11_BLEND_OP_ADD,
+      D3D11_COLOR_WRITE_ENABLE_ALL
+    };
+    blendDesc.RenderTarget[0] = rtBlendScreenPremul;
+    hr = mDevice->CreateBlendState(&blendDesc, byRef(mAttachments->mPremulBlendScreenState));
+    if (FAILED(hr)) {
+      return false;
+    }
+
     D3D11_RENDER_TARGET_BLEND_DESC rtBlendNonPremul = {
       TRUE,
       D3D11_BLEND_SRC_ALPHA, D3D11_BLEND_INV_SRC_ALPHA, D3D11_BLEND_OP_ADD,
       D3D11_BLEND_ONE, D3D11_BLEND_INV_SRC_ALPHA, D3D11_BLEND_OP_ADD,
       D3D11_COLOR_WRITE_ENABLE_ALL
     };
     blendDesc.RenderTarget[0] = rtBlendNonPremul;
     hr = mDevice->CreateBlendState(&blendDesc, byRef(mAttachments->mNonPremulBlendState));
@@ -415,16 +477,18 @@ CompositorD3D11::GetTextureFactoryIdenti
   if (mAttachments->mSyncTexture) {
     HRESULT hr = mAttachments->mSyncTexture->GetSharedHandle(&ident.mSyncHandle);
     if (FAILED(hr) || !ident.mSyncHandle) {
       gfxCriticalError() << "Failed to get SharedHandle for sync texture. Result: "
                          << hexa(hr);
       MOZ_CRASH();
     }
   }
+  ident.mSupportedBlendModes += gfx::CompositionOp::OP_SCREEN;
+  ident.mSupportedBlendModes += gfx::CompositionOp::OP_MULTIPLY;
   return ident;
 }
 
 bool
 CompositorD3D11::CanUseCanvasLayerForSize(const gfx::IntSize& aSize)
 {
   int32_t maxTextureSize = GetMaxTextureSize();
 
@@ -556,31 +620,24 @@ CompositorD3D11::SetRenderTarget(Composi
 
 void
 CompositorD3D11::SetPSForEffect(Effect* aEffect, MaskType aMaskType, gfx::SurfaceFormat aFormat)
 {
   switch (aEffect->mType) {
   case EffectTypes::SOLID_COLOR:
     mContext->PSSetShader(mAttachments->mSolidColorShader[aMaskType], nullptr, 0);
     return;
-  case EffectTypes::RENDER_TARGET:
-    mContext->PSSetShader(mAttachments->mRGBAShader[aMaskType], nullptr, 0);
-    return;
-  case EffectTypes::RGB:
-    mContext->PSSetShader((aFormat == SurfaceFormat::B8G8R8A8 || aFormat == SurfaceFormat::R8G8B8A8)
-                          ? mAttachments->mRGBAShader[aMaskType]
-                          : mAttachments->mRGBShader[aMaskType], nullptr, 0);
-    return;
   case EffectTypes::YCBCR:
     mContext->PSSetShader(mAttachments->mYCbCrShader[aMaskType], nullptr, 0);
     return;
   case EffectTypes::COMPONENT_ALPHA:
     mContext->PSSetShader(mAttachments->mComponentAlphaShader[aMaskType], nullptr, 0);
     return;
   default:
+    // Note: the RGB and RENDER_TARGET cases are handled in-line in DrawQuad().
     NS_WARNING("No shader to load");
     return;
   }
 }
 
 void
 CompositorD3D11::ClearRect(const gfx::Rect& aRect)
 {
@@ -837,26 +894,33 @@ CompositorD3D11::DrawQuad(const gfx::Rec
   scissor.bottom = clipRect.YMost();
 
   mContext->RSSetScissorRects(1, &scissor);
   mContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
   mContext->VSSetShader(mAttachments->mVSQuadShader[maskType], nullptr, 0);
 
   const Rect* pTexCoordRect = nullptr;
 
+  gfx::CompositionOp blendMode = gfx::CompositionOp::OP_OVER;
+  if (Effect* effect = aEffectChain.mSecondaryEffects[EffectTypes::BLEND_MODE].get()) {
+    blendMode = static_cast<EffectBlendMode*>(effect)->mBlendMode;
+  }
+
   switch (aEffectChain.mPrimaryEffect->mType) {
   case EffectTypes::SOLID_COLOR: {
       SetPSForEffect(aEffectChain.mPrimaryEffect, maskType, SurfaceFormat::UNKNOWN);
 
       Color color =
         static_cast<EffectSolidColor*>(aEffectChain.mPrimaryEffect.get())->mColor;
       mPSConstants.layerColor[0] = color.r * color.a * aOpacity;
       mPSConstants.layerColor[1] = color.g * color.a * aOpacity;
       mPSConstants.layerColor[2] = color.b * color.a * aOpacity;
       mPSConstants.layerColor[3] = color.a * aOpacity;
+
+      restoreBlendMode = SetBlendMode(blendMode);
     }
     break;
   case EffectTypes::RGB:
   case EffectTypes::RENDER_TARGET:
     {
       TexturedEffect* texturedEffect =
         static_cast<TexturedEffect*>(aEffectChain.mPrimaryEffect.get());
 
@@ -864,25 +928,37 @@ CompositorD3D11::DrawQuad(const gfx::Rec
 
       TextureSourceD3D11* source = texturedEffect->mTexture->AsSourceD3D11();
 
       if (!source) {
         NS_WARNING("Missing texture source!");
         return;
       }
 
-      SetPSForEffect(aEffectChain.mPrimaryEffect, maskType, texturedEffect->mTexture->GetFormat());
+      SurfaceFormat format = texturedEffect->mTexture->GetFormat();
+      bool useRGBAShader = (format == SurfaceFormat::B8G8R8A8 || format == SurfaceFormat::R8G8B8A8) ||
+                           (texturedEffect->mType == EffectTypes::RENDER_TARGET);
+
+      bool premultiplied = texturedEffect->mPremultiplied;
+      if (!premultiplied && useRGBAShader &&
+          (blendMode == CompositionOp::OP_MULTIPLY ||
+           blendMode == CompositionOp::OP_SCREEN))
+      {
+        mContext->PSSetShader(mAttachments->mRGBAShaderPremul[maskType], nullptr, 0);
+        premultiplied = true;
+      } else if (useRGBAShader) {
+        mContext->PSSetShader(mAttachments->mRGBAShader[maskType], nullptr, 0);
+      } else {
+        mContext->PSSetShader(mAttachments->mRGBShader[maskType], nullptr, 0);
+      }
 
       ID3D11ShaderResourceView* srView = source->GetShaderResourceView();
       mContext->PSSetShaderResources(0, 1, &srView);
 
-      if (!texturedEffect->mPremultiplied) {
-        mContext->OMSetBlendState(mAttachments->mNonPremulBlendState, sBlendFactor, 0xFFFFFFFF);
-        restoreBlendMode = true;
-      }
+      restoreBlendMode = SetBlendMode(blendMode, premultiplied);
 
       SetSamplerForFilter(texturedEffect->mFilter);
     }
     break;
   case EffectTypes::YCBCR: {
       EffectYCbCr* ycbcrEffect =
         static_cast<EffectYCbCr*>(aEffectChain.mPrimaryEffect.get());
 
@@ -909,16 +985,18 @@ CompositorD3D11::DrawQuad(const gfx::Rec
       TextureSourceD3D11* sourceY  = source->GetSubSource(Y)->AsSourceD3D11();
       TextureSourceD3D11* sourceCb = source->GetSubSource(Cb)->AsSourceD3D11();
       TextureSourceD3D11* sourceCr = source->GetSubSource(Cr)->AsSourceD3D11();
 
       ID3D11ShaderResourceView* srViews[3] = { sourceY->GetShaderResourceView(),
                                                sourceCb->GetShaderResourceView(),
                                                sourceCr->GetShaderResourceView() };
       mContext->PSSetShaderResources(0, 3, srViews);
+
+      restoreBlendMode = SetBlendMode(blendMode);
     }
     break;
   case EffectTypes::COMPONENT_ALPHA:
     {
       MOZ_ASSERT(gfxPrefs::ComponentAlphaEnabled());
       MOZ_ASSERT(mAttachments->mComponentBlendState);
       EffectComponentAlpha* effectComponentAlpha =
         static_cast<EffectComponentAlpha*>(aEffectChain.mPrimaryEffect.get());
@@ -936,16 +1014,17 @@ CompositorD3D11::DrawQuad(const gfx::Rec
       SetSamplerForFilter(effectComponentAlpha->mFilter);
 
       pTexCoordRect = &effectComponentAlpha->mTextureCoords;
 
       ID3D11ShaderResourceView* srViews[2] = { sourceOnBlack->GetShaderResourceView(),
                                                sourceOnWhite->GetShaderResourceView() };
       mContext->PSSetShaderResources(0, 2, srViews);
 
+      // Note: component alpha is never used in blend containers.
       mContext->OMSetBlendState(mAttachments->mComponentBlendState, sBlendFactor, 0xFFFFFFFF);
       restoreBlendMode = true;
     }
     break;
   default:
     NS_WARNING("Unknown shader type");
     return;
   }
@@ -977,16 +1056,49 @@ CompositorD3D11::DrawQuad(const gfx::Rec
     }
   }
 
   if (restoreBlendMode) {
     mContext->OMSetBlendState(mAttachments->mPremulBlendState, sBlendFactor, 0xFFFFFFFF);
   }
 }
 
+bool
+CompositorD3D11::SetBlendMode(gfx::CompositionOp aOp, bool aPremultiplied)
+{
+  if (aOp == gfx::CompositionOp::OP_OVER && aPremultiplied) {
+    return false;
+  }
+
+  ID3D11BlendState* blendState = nullptr;
+
+  switch (aOp) {
+    case gfx::CompositionOp::OP_OVER:
+      MOZ_ASSERT(!aPremultiplied);
+      blendState = mAttachments->mNonPremulBlendState;
+      break;
+    case gfx::CompositionOp::OP_MULTIPLY:
+      // Premultiplication is handled in the shader.
+      MOZ_ASSERT(aPremultiplied);
+      blendState = mAttachments->mPremulBlendMultiplyState;
+      break;
+    case gfx::CompositionOp::OP_SCREEN:
+      // Premultiplication is handled in the shader.
+      MOZ_ASSERT(aPremultiplied);
+      blendState = mAttachments->mPremulBlendScreenState;
+      break;
+    default:
+      MOZ_ASSERT_UNREACHABLE("Unsupported blend mode!");
+      return false;
+  }
+
+  mContext->OMSetBlendState(blendState, sBlendFactor, 0xFFFFFFFF);
+  return true;
+}
+
 void
 CompositorD3D11::BeginFrame(const nsIntRegion& aInvalidRegion,
                             const Rect* aClipRectIn,
                             const Rect& aRenderBounds,
                             Rect* aClipRectOut,
                             Rect* aRenderBoundsOut)
 {
   // Don't composite if we are minimised. Other than for the sake of efficency,
@@ -1231,96 +1343,47 @@ CompositorD3D11::UpdateRenderTarget()
     return;
   }
 
   mDefaultRT = new CompositingRenderTargetD3D11(backBuf, IntPoint(0, 0));
   mDefaultRT->SetSize(mSize);
 }
 
 bool
-CompositorD3D11::CreateShaders()
+DeviceAttachmentsD3D11::CreateShaders()
 {
-  HRESULT hr;
-
-  hr = mDevice->CreateVertexShader(LayerQuadVS,
-                                   sizeof(LayerQuadVS),
-                                   nullptr,
-                                   byRef(mAttachments->mVSQuadShader[MaskType::MaskNone]));
-  if (FAILED(hr)) {
-    return false;
-  }
+  InitVertexShader(sLayerQuadVS, mVSQuadShader, MaskType::MaskNone);
+  InitVertexShader(sLayerQuadMaskVS, mVSQuadShader, MaskType::Mask2d);
+  InitVertexShader(sLayerQuadMask3DVS, mVSQuadShader, MaskType::Mask3d);
 
-  hr = mDevice->CreateVertexShader(LayerQuadMaskVS,
-                                   sizeof(LayerQuadMaskVS),
-                                   nullptr,
-                                   byRef(mAttachments->mVSQuadShader[MaskType::Mask2d]));
-  if (FAILED(hr)) {
-    return false;
-  }
-
-  hr = mDevice->CreateVertexShader(LayerQuadMask3DVS,
-                                   sizeof(LayerQuadMask3DVS),
-                                   nullptr,
-                                   byRef(mAttachments->mVSQuadShader[MaskType::Mask3d]));
-  if (FAILED(hr)) {
-    return false;
-  }
-
-#define LOAD_PIXEL_SHADER(x) hr = mDevice->CreatePixelShader(x, sizeof(x), nullptr, byRef(mAttachments->m##x[MaskType::MaskNone])); \
-  if (FAILED(hr)) { \
-    return false; \
-  } \
-  hr = mDevice->CreatePixelShader(x##Mask, sizeof(x##Mask), nullptr, byRef(mAttachments->m##x[MaskType::Mask2d])); \
-  if (FAILED(hr)) { \
-    return false; \
+  InitPixelShader(sSolidColorShader, mSolidColorShader, MaskType::MaskNone);
+  InitPixelShader(sSolidColorShaderMask, mSolidColorShader, MaskType::Mask2d);
+  InitPixelShader(sRGBShader, mRGBShader, MaskType::MaskNone);
+  InitPixelShader(sRGBShaderMask, mRGBShader, MaskType::Mask2d);
+  InitPixelShader(sRGBAShader, mRGBAShader, MaskType::MaskNone);
+  InitPixelShader(sRGBAShaderMask, mRGBAShader, MaskType::Mask2d);
+  InitPixelShader(sRGBAShaderMask3D, mRGBAShader, MaskType::Mask3d);
+  InitPixelShader(sRGBAShaderPremul, mRGBAShaderPremul, MaskType::MaskNone);
+  InitPixelShader(sRGBAShaderMaskPremul, mRGBAShaderPremul, MaskType::Mask2d);
+  InitPixelShader(sRGBAShaderMask3DPremul, mRGBAShaderPremul, MaskType::Mask3d);
+  InitPixelShader(sYCbCrShader, mYCbCrShader, MaskType::MaskNone);
+  InitPixelShader(sYCbCrShaderMask, mYCbCrShader, MaskType::Mask2d);
+  if (gfxPrefs::ComponentAlphaEnabled()) {
+    InitPixelShader(sComponentAlphaShader, mComponentAlphaShader, MaskType::MaskNone);
+    InitPixelShader(sComponentAlphaShaderMask, mComponentAlphaShader, MaskType::Mask2d);
   }
 
-  LOAD_PIXEL_SHADER(SolidColorShader);
-  LOAD_PIXEL_SHADER(RGBShader);
-  LOAD_PIXEL_SHADER(RGBAShader);
-  LOAD_PIXEL_SHADER(YCbCrShader);
-  if (gfxPrefs::ComponentAlphaEnabled()) {
-    LOAD_PIXEL_SHADER(ComponentAlphaShader);
-  }
-
-#undef LOAD_PIXEL_SHADER
-
-  hr = mDevice->CreatePixelShader(RGBAShaderMask3D,
-                                  sizeof(RGBAShaderMask3D),
-                                  nullptr,
-                                  byRef(mAttachments->mRGBAShader[MaskType::Mask3d]));
-  if (FAILED(hr)) {
-    return false;
-  }
-
-
-  /* VR stuff */
-
-  hr = mDevice->CreateVertexShader(Oculus050VRDistortionVS,
-                                   sizeof(Oculus050VRDistortionVS),
-                                   nullptr,
-                                   byRef(mAttachments->mVRDistortionVS[VRHMDType::Oculus050]));
-  if (FAILED(hr)) {
-    return false;
-  }
-
-  hr = mDevice->CreatePixelShader(Oculus050VRDistortionPS,
-                                  sizeof(Oculus050VRDistortionPS),
-                                  nullptr,
-                                  byRef(mAttachments->mVRDistortionPS[VRHMDType::Oculus050]));
-  if (FAILED(hr)) {
-    return false;
-  }
+  InitVertexShader(sOculus050VRDistortionVS, byRef(mVRDistortionVS[VRHMDType::Oculus050]));
+  InitPixelShader(sOculus050VRDistortionPS, byRef(mVRDistortionPS[VRHMDType::Oculus050]));
 
   // These are shared
   // XXX rename Oculus050 shaders to something more generic
-  mAttachments->mVRDistortionVS[VRHMDType::Cardboard] = mAttachments->mVRDistortionVS[VRHMDType::Oculus050];
-  mAttachments->mVRDistortionPS[VRHMDType::Cardboard] = mAttachments->mVRDistortionPS[VRHMDType::Oculus050];
-
-  return true;
+  mVRDistortionVS[VRHMDType::Cardboard] = mVRDistortionVS[VRHMDType::Oculus050];
+  mVRDistortionPS[VRHMDType::Cardboard] = mVRDistortionPS[VRHMDType::Oculus050];
+  return mInitOkay;
 }
 
 bool
 CompositorD3D11::UpdateConstantBuffers()
 {
   HRESULT hr;
   D3D11_MAPPED_SUBRESOURCE resource;
   resource.pData = nullptr;
--- a/gfx/layers/d3d11/CompositorD3D11.h
+++ b/gfx/layers/d3d11/CompositorD3D11.h
@@ -159,21 +159,21 @@ private:
   void HandleError(HRESULT hr, Severity aSeverity = DebugAssert);
   bool Failed(HRESULT hr, Severity aSeverity = DebugAssert);
   bool Succeeded(HRESULT hr, Severity aSeverity = DebugAssert);
 
   // ensure mSize is up to date with respect to mWidget
   void EnsureSize();
   bool VerifyBufferSize();
   void UpdateRenderTarget();
-  bool CreateShaders();
   bool UpdateConstantBuffers();
   void SetSamplerForFilter(gfx::Filter aFilter);
   void SetPSForEffect(Effect *aEffect, MaskType aMaskType, gfx::SurfaceFormat aFormat);
   void PaintToTarget();
+  bool SetBlendMode(gfx::CompositionOp aOp, bool aPremultipled = true);
 
   virtual gfx::IntSize GetWidgetSize() const override { return mSize; }
 
   RefPtr<ID3D11DeviceContext> mContext;
   RefPtr<ID3D11Device> mDevice;
   RefPtr<IDXGISwapChain> mSwapChain;
   RefPtr<CompositingRenderTargetD3D11> mDefaultRT;
   RefPtr<CompositingRenderTargetD3D11> mCurrentRT;
--- a/gfx/layers/d3d11/CompositorD3D11.hlsl
+++ b/gfx/layers/d3d11/CompositorD3D11.hlsl
@@ -158,23 +158,37 @@ VS_MASK_3D_OUTPUT LayerQuadMask3DVS(cons
 
 float4 RGBAShaderMask(const VS_MASK_OUTPUT aVertex) : SV_Target
 {
   float2 maskCoords = aVertex.vMaskCoords;
   float mask = tMask.Sample(sSampler, maskCoords).r;
   return tRGB.Sample(sSampler, aVertex.vTexCoords) * fLayerOpacity * mask;
 }
 
+float4 RGBAShaderMaskPremul(const VS_MASK_OUTPUT aVertex) : SV_Target
+{
+  float4 result = RGBAShaderMask(aVertex);
+  result.rgb *= result.a;
+  return result;
+}
+
 float4 RGBAShaderMask3D(const VS_MASK_3D_OUTPUT aVertex) : SV_Target
 {
   float2 maskCoords = aVertex.vMaskCoords.xy / aVertex.vMaskCoords.z;
   float mask = tMask.Sample(LayerTextureSamplerLinear, maskCoords).r;
   return tRGB.Sample(sSampler, aVertex.vTexCoords) * fLayerOpacity * mask;
 }
 
+float4 RGBAShaderMask3DPremul(const VS_MASK_3D_OUTPUT aVertex) : SV_Target
+{
+  float4 result = RGBAShaderMask3D(aVertex);
+  result.rgb *= result.a;
+  return result;
+}
+
 float4 RGBShaderMask(const VS_MASK_OUTPUT aVertex) : SV_Target
 {
   float4 result;
   result = tRGB.Sample(sSampler, aVertex.vTexCoords) * fLayerOpacity;
   result.a = fLayerOpacity;
 
   float2 maskCoords = aVertex.vMaskCoords;
   float mask = tMask.Sample(sSampler, maskCoords).r;
@@ -243,16 +257,23 @@ float4 SolidColorShaderMask(const VS_MAS
  *  Un-masked versions
  *************************************************************
  */
 float4 RGBAShader(const VS_OUTPUT aVertex) : SV_Target
 {
   return tRGB.Sample(sSampler, aVertex.vTexCoords) * fLayerOpacity;
 }
 
+float4 RGBAShaderPremul(const VS_OUTPUT aVertex) : SV_Target
+{
+  float4 result = RGBAShader(aVertex);
+  result.rgb *= result.a;
+  return result;
+}
+
 float4 RGBShader(const VS_OUTPUT aVertex) : SV_Target
 {
   float4 result;
   result = tRGB.Sample(sSampler, aVertex.vTexCoords) * fLayerOpacity;
   result.a = fLayerOpacity;
   return result;
 }
 
--- a/gfx/layers/d3d11/CompositorD3D11Shaders.h
+++ b/gfx/layers/d3d11/CompositorD3D11Shaders.h
@@ -1,15 +1,12 @@
+struct ShaderBytes { const void* mData; size_t mLength; };
 #if 0
 //
-// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111
-//
-//
-//   fxc -nologo -Tvs_4_0_level_9_3 CompositorD3D11.hlsl -ELayerQuadVS
-//    -VnLayerQuadVS -FhtmpShaderHeader
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
 //
 //
 // Buffer Definitions: 
 //
 // cbuffer $Globals
 // {
 //
 //   float4x4 mLayerTransform;          // Offset:    0 Size:    64
@@ -29,27 +26,27 @@
 // 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  
+// Name                 Index   Mask Register SysValue  Format   Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// POSITION                 0   xy          0     NONE   float   xy  
 //
 //
 // Output signature:
 //
-// Name                 Index   Mask Register SysValue Format   Used
-// -------------------- ----- ------ -------- -------- ------ ------
-// SV_Position              0   xyzw        0      POS  float   xyzw
-// TEXCOORD                 0   xy          1     NONE  float   xy  
+// Name                 Index   Mask Register SysValue  Format   Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_Position              0   xyzw        0      POS   float   xyzw
+// TEXCOORD                 0   xy          1     NONE   float   xy  
 //
 //
 // Constant buffer to DX9 shader constant mappings:
 //
 // Target Reg Buffer  Start Reg # of Regs        Data Conversion
 // ---------- ------- --------- --------- ----------------------
 // c1         cb0             0         2  ( FLT, FLT, FLT, FLT)
 // c3         cb0             3         8  ( FLT, FLT, FLT, FLT)
@@ -102,20 +99,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,  26, 156, 
-     32, 249,  73, 220,  32,  91, 
-     64, 185, 136, 143, 133, 249, 
-    140, 206,   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, 
@@ -260,27 +257,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,   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, 
       4,   2,   0,   0,   1,   0, 
@@ -361,20 +358,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,  50,  57,  46,  57,  53, 
-     50,  46,  51,  49,  49,  49, 
-      0, 171, 171, 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, 
@@ -389,23 +386,20 @@ const BYTE LayerQuadVS[] =
       0,   0,   0,   0,   0,   0, 
       3,   0,   0,   0,   1,   0, 
       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
 };
+ShaderBytes sLayerQuadVS = { LayerQuadVS, sizeof(LayerQuadVS) };
 #if 0
 //
-// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111
-//
-//
-//   fxc -nologo -Tps_4_0_level_9_3 CompositorD3D11.hlsl -ESolidColorShader
-//    -VnSolidColorShader -FhtmpShaderHeader
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
 //
 //
 // Buffer Definitions: 
 //
 // cbuffer $Globals
 // {
 //
 //   float4 fLayerColor;                // Offset:    0 Size:    16
@@ -425,27 +419,27 @@ const BYTE LayerQuadVS[] =
 // Name                                 Type  Format         Dim Slot Elements
 // ------------------------------ ---------- ------- ----------- ---- --------
 // $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       
+// Name                 Index   Mask Register SysValue  Format   Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_Position              0   xyzw        0      POS   float       
+// TEXCOORD                 0   xy          1     NONE   float       
 //
 //
 // Output signature:
 //
-// Name                 Index   Mask Register SysValue Format   Used
-// -------------------- ----- ------ -------- -------- ------ ------
-// SV_Target                0   xyzw        0   TARGET  float   xyzw
+// 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             0         1  ( FLT, FLT, FLT, FLT)
 //
@@ -461,20 +455,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, 204,   8, 
-      5, 100,  51,  20, 107, 176, 
-    111, 165, 149, 245, 134, 187, 
-     83,  96,   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, 
@@ -600,19 +594,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,  50,  57, 
-     46,  57,  53,  50,  46,  51, 
-     49,  49,  49,   0, 171, 171, 
+    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, 
@@ -628,23 +622,20 @@ const BYTE SolidColorShader[] =
       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
 };
+ShaderBytes sSolidColorShader = { SolidColorShader, sizeof(SolidColorShader) };
 #if 0
 //
-// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111
-//
-//
-//   fxc -nologo -Tps_4_0_level_9_3 CompositorD3D11.hlsl -ERGBShader
-//    -VnRGBShader -FhtmpShaderHeader
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
 //
 //
 // Buffer Definitions: 
 //
 // cbuffer $Globals
 // {
 //
 //   float4 fLayerColor;                // Offset:    0 Size:    16 [unused]
@@ -666,27 +657,27 @@ const BYTE SolidColorShader[] =
 // 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  
+// 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
+// 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)
 //
@@ -720,20 +711,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,  20, 109, 
-    176, 198,  26, 112, 108, 185, 
-    246, 240, 143,  18,  57, 236, 
-    126,  68,   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, 
@@ -903,19 +894,19 @@ const BYTE RGBShader[] =
      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,  50,  57, 
-     46,  57,  53,  50,  46,  51, 
-     49,  49,  49,   0, 171, 171, 
+    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, 
@@ -931,23 +922,20 @@ const BYTE RGBShader[] =
       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
 };
+ShaderBytes sRGBShader = { RGBShader, sizeof(RGBShader) };
 #if 0
 //
-// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111
-//
-//
-//   fxc -nologo -Tps_4_0_level_9_3 CompositorD3D11.hlsl -ERGBAShader
-//    -VnRGBAShader -FhtmpShaderHeader
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
 //
 //
 // Buffer Definitions: 
 //
 // cbuffer $Globals
 // {
 //
 //   float4 fLayerColor;                // Offset:    0 Size:    16 [unused]
@@ -969,27 +957,27 @@ const BYTE RGBShader[] =
 // 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  
+// 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
+// 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)
 //
@@ -1021,20 +1009,20 @@ 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, 214,  26, 
-    168, 112,  65, 151,  75,  99, 
-    196,  63, 136, 104, 158, 202, 
-    217,   7,   1,   0,   0,   0, 
+     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, 
@@ -1198,19 +1186,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,  50,  57, 
-     46,  57,  53,  50,  46,  51, 
-     49,  49,  49,   0, 171, 171, 
+    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, 
@@ -1226,23 +1214,325 @@ const BYTE RGBAShader[] =
       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
 };
+ShaderBytes sRGBAShader = { RGBAShader, sizeof(RGBAShader) };
 #if 0
 //
-// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111
-//
-//
-//   fxc -nologo -Tps_4_0_level_9_3 CompositorD3D11.hlsl -EComponentAlphaShader
-//    -VnComponentAlphaShader -FhtmpShaderHeader
+// 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
+    mul r0.xyz, r0.w, r0
+    mov oC0, r0
+
+// approximately 4 instruction slots used (1 texture, 3 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 r0.xyzw, r0.xyzw, cb0[1].xxxx
+mul o0.xyz, r0.wwww, r0.xyzx
+mov o0.w, r0.w
+ret 
+// Approximately 5 instruction slots used
+#endif
+
+const BYTE RGBAShaderPremul[] =
+{
+     68,  88,  66,  67,   9,  19, 
+    234, 250, 161,  24, 191,  52, 
+    148,  34, 157,  98,  40,  39, 
+     76,  48,   1,   0,   0,   0, 
+      4,   5,   0,   0,   6,   0, 
+      0,   0,  56,   0,   0,   0, 
+    208,   0,   0,   0, 164,   1, 
+      0,   0,  32,   2,   0,   0, 
+    120,   4,   0,   0, 208,   4, 
+      0,   0,  65, 111, 110,  57, 
+    144,   0,   0,   0, 144,   0, 
+      0,   0,   0,   2, 255, 255, 
+     92,   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,   5,   0,   0,   3, 
+      0,   0,   7, 128,   0,   0, 
+    255, 128,   0,   0, 228, 128, 
+      1,   0,   0,   2,   0,   8, 
+     15, 128,   0,   0, 228, 128, 
+    255, 255,   0,   0,  83,  72, 
+     68,  82, 204,   0,   0,   0, 
+     64,   0,   0,   0,  51,   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,   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,  56,   0,   0,   7, 
+    114,  32,  16,   0,   0,   0, 
+      0,   0, 246,  15,  16,   0, 
+      0,   0,   0,   0,  70,   2, 
+     16,   0,   0,   0,   0,   0, 
+     54,   0,   0,   5, 130,  32, 
+     16,   0,   0,   0,   0,   0, 
+     58,   0,  16,   0,   0,   0, 
+      0,   0,  62,   0,   0,   1, 
+     83,  84,  65,  84, 116,   0, 
+      0,   0,   5,   0,   0,   0, 
+      1,   0,   0,   0,   0,   0, 
+      0,   0,   2,   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,   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,   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
+};
+ShaderBytes sRGBAShaderPremul = { RGBAShaderPremul, sizeof(RGBAShaderPremul) };
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
 //
 //
 // Buffer Definitions: 
 //
 // cbuffer $Globals
 // {
 //
 //   float4 fLayerColor;                // Offset:    0 Size:    16 [unused]
@@ -1265,28 +1555,28 @@ const BYTE RGBAShader[] =
 // tRGB                              texture  float4          2d    0        1
 // tRGBWhite                         texture  float4          2d    1        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  
+// 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
-// SV_Target                1   xyzw        1   TARGET  float   xyzw
+// Name                 Index   Mask Register SysValue  Format   Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_Target                0   xyzw        0   TARGET   float   xyzw
+// SV_Target                1   xyzw        1   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)
 //
@@ -1334,20 +1624,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, 207, 238, 
-    180, 151, 111,  52, 137,   3, 
-     45, 243, 229, 223,  99, 172, 
-     89,   3,   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, 
@@ -1460,17 +1750,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, 
-      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, 124,   2,   0,   0, 
       1,   0,   0,   0, 192,   0, 
@@ -1571,19 +1861,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,  50,  57, 
-     46,  57,  53,  50,  46,  51, 
-     49,  49,  49,   0, 171, 171, 
+    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, 
@@ -1603,23 +1893,20 @@ const BYTE ComponentAlphaShader[] =
       0,   0,  56,   0,   0,   0, 
       1,   0,   0,   0,   0,   0, 
       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
 };
+ShaderBytes sComponentAlphaShader = { ComponentAlphaShader, sizeof(ComponentAlphaShader) };
 #if 0
 //
-// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111
-//
-//
-//   fxc -nologo -Tps_4_0_level_9_3 CompositorD3D11.hlsl -EYCbCrShader
-//    -VnYCbCrShader -FhtmpShaderHeader
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
 //
 //
 // Buffer Definitions: 
 //
 // cbuffer $Globals
 // {
 //
 //   float4 fLayerColor;                // Offset:    0 Size:    16 [unused]
@@ -1643,27 +1930,27 @@ const BYTE ComponentAlphaShader[] =
 // tCb                               texture  float4          2d    1        1
 // tCr                               texture  float4          2d    2        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  
+// 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
+// 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)
 //
@@ -1727,20 +2014,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,  54,  63, 
-    153,   7,  84, 231,  22,  28, 
-    117, 160,  57,  24, 123, 163, 
-     52, 109,   1,   0,   0,   0, 
+     68,  88,  66,  67, 127, 202, 
+     65,  67, 171,  51, 222, 111, 
+    252, 139,  60, 115,  30, 112, 
+    240,  10,   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, 
@@ -1909,17 +2196,17 @@ 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, 
@@ -2035,19 +2322,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,  50,  57,  46,  57, 
-     53,  50,  46,  51,  49,  49, 
-     49,   0, 171, 171,  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, 
@@ -2062,23 +2349,20 @@ const BYTE YCbCrShader[] =
       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
 };
+ShaderBytes sYCbCrShader = { YCbCrShader, sizeof(YCbCrShader) };
 #if 0
 //
-// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111
-//
-//
-//   fxc -nologo -Tvs_4_0_level_9_3 CompositorD3D11.hlsl -ELayerQuadMaskVS
-//    -VnLayerQuadMaskVS -FhtmpShaderHeader
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
 //
 //
 // Buffer Definitions: 
 //
 // cbuffer $Globals
 // {
 //
 //   float4x4 mLayerTransform;          // Offset:    0 Size:    64
@@ -2098,28 +2382,28 @@ const BYTE YCbCrShader[] =
 // 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  
+// Name                 Index   Mask Register SysValue  Format   Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// POSITION                 0   xy          0     NONE   float   xy  
 //
 //
 // Output signature:
 //
-// Name                 Index   Mask Register SysValue Format   Used
-// -------------------- ----- ------ -------- -------- ------ ------
-// SV_Position              0   xyzw        0      POS  float   xyzw
-// TEXCOORD                 0   xy          1     NONE  float   xy  
-// TEXCOORD                 1     zw        1     NONE  float     zw
+// Name                 Index   Mask Register SysValue  Format   Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_Position              0   xyzw        0      POS   float   xyzw
+// TEXCOORD                 0   xy          1     NONE   float   xy  
+// TEXCOORD                 1     zw        1     NONE   float     zw
 //
 //
 // Constant buffer to DX9 shader constant mappings:
 //
 // Target Reg Buffer  Start Reg # of Regs        Data Conversion
 // ---------- ------- --------- --------- ----------------------
 // c1         cb0             0         2  ( FLT, FLT, FLT, FLT)
 // c3         cb0             3         9  ( FLT, FLT, FLT, FLT)
@@ -2181,20 +2465,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,  15, 196, 
-    252, 199, 211, 188,  92,  26, 
-     46, 113, 249,  29, 135, 110, 
-     83, 119,   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, 
@@ -2368,17 +2652,17 @@ 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, 
@@ -2469,19 +2753,19 @@ 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,  50, 
-     57,  46,  57,  53,  50,  46, 
-     51,  49,  49,  49,   0, 171, 
+    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, 
@@ -2501,23 +2785,20 @@ const BYTE LayerQuadMaskVS[] =
       0,   0,   0,   0,   3,   0, 
       0,   0,   1,   0,   0,   0, 
      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
 };
+ShaderBytes sLayerQuadMaskVS = { LayerQuadMaskVS, sizeof(LayerQuadMaskVS) };
 #if 0
 //
-// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111
-//
-//
-//   fxc -nologo -Tvs_4_0_level_9_3 CompositorD3D11.hlsl -ELayerQuadMask3DVS
-//    -VnLayerQuadMask3DVS -FhtmpShaderHeader
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
 //
 //
 // Buffer Definitions: 
 //
 // cbuffer $Globals
 // {
 //
 //   float4x4 mLayerTransform;          // Offset:    0 Size:    64
@@ -2537,28 +2818,28 @@ const BYTE LayerQuadMaskVS[] =
 // 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  
+// Name                 Index   Mask Register SysValue  Format   Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// POSITION                 0   xy          0     NONE   float   xy  
 //
 //
 // Output signature:
 //
-// Name                 Index   Mask Register SysValue Format   Used
-// -------------------- ----- ------ -------- -------- ------ ------
-// SV_Position              0   xyzw        0      POS  float   xyzw
-// TEXCOORD                 0   xy          1     NONE  float   xy  
-// TEXCOORD                 1   xyz         2     NONE  float   xyz 
+// Name                 Index   Mask Register SysValue  Format   Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_Position              0   xyzw        0      POS   float   xyzw
+// TEXCOORD                 0   xy          1     NONE   float   xy  
+// TEXCOORD                 1   xyz         2     NONE   float   xyz 
 //
 //
 // Constant buffer to DX9 shader constant mappings:
 //
 // Target Reg Buffer  Start Reg # of Regs        Data Conversion
 // ---------- ------- --------- --------- ----------------------
 // c1         cb0             0         2  ( FLT, FLT, FLT, FLT)
 // c3         cb0             3         9  ( FLT, FLT, FLT, FLT)
@@ -2624,20 +2905,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, 100,  40, 
-     55,  29, 238,  71, 107,  78, 
-    214, 182,  73, 149, 138,  22, 
-    163, 187,   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, 
@@ -2825,27 +3106,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,   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, 
@@ -2926,19 +3207,19 @@ 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,  50, 
-     57,  46,  57,  53,  50,  46, 
-     51,  49,  49,  49,   0, 171, 
+    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, 
@@ -2958,23 +3239,20 @@ const BYTE LayerQuadMask3DVS[] =
       0,   0,   0,   0,   3,   0, 
       0,   0,   2,   0,   0,   0, 
       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
 };
+ShaderBytes sLayerQuadMask3DVS = { LayerQuadMask3DVS, sizeof(LayerQuadMask3DVS) };
 #if 0
 //
-// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111
-//
-//
-//   fxc -nologo -Tps_4_0_level_9_3 CompositorD3D11.hlsl -ESolidColorShaderMask
-//    -VnSolidColorShaderMask -FhtmpShaderHeader
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
 //
 //
 // Buffer Definitions: 
 //
 // cbuffer $Globals
 // {
 //
 //   float4 fLayerColor;                // Offset:    0 Size:    16
@@ -2996,28 +3274,28 @@ const BYTE LayerQuadMask3DVS[] =
 // sSampler                          sampler      NA          NA    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       
-// TEXCOORD                 1     zw        1     NONE  float     zw
+// Name                 Index   Mask Register SysValue  Format   Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_Position              0   xyzw        0      POS   float       
+// TEXCOORD                 0   xy          1     NONE   float       
+// TEXCOORD                 1     zw        1     NONE   float     zw
 //
 //
 // Output signature:
 //
-// Name                 Index   Mask Register SysValue Format   Used
-// -------------------- ----- ------ -------- -------- ------ ------
-// SV_Target                0   xyzw        0   TARGET  float   xyzw
+// 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             0         1  ( FLT, FLT, FLT, FLT)
 //
@@ -3050,20 +3328,20 @@ dcl_temps 1
 sample r0.xyzw, v1.zwzz, t3.xyzw, s0
 mul o0.xyzw, r0.xxxx, cb0[0].xyzw
 ret 
 // Approximately 3 instruction slots used
 #endif
 
 const BYTE SolidColorShaderMask[] =
 {
-     68,  88,  66,  67, 218,  73, 
-     87,  32, 206,  67,  79,  54, 
-     31, 104, 228, 152, 133, 115, 
-    245,   3,   1,   0,   0,   0, 
+     68,  88,  66,  67, 189,  88, 
+    190, 169, 235, 115, 239, 219, 
+    181, 194, 113, 122, 250, 177, 
+    212, 243,   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, 
@@ -3229,19 +3507,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,  50,  57, 
-     46,  57,  53,  50,  46,  51, 
-     49,  49,  49,   0, 171, 171, 
+    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, 
@@ -3261,23 +3539,20 @@ const BYTE SolidColorShaderMask[] =
       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
 };
+ShaderBytes sSolidColorShaderMask = { SolidColorShaderMask, sizeof(SolidColorShaderMask) };
 #if 0
 //
-// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111
-//
-//
-//   fxc -nologo -Tps_4_0_level_9_3 CompositorD3D11.hlsl -ERGBShaderMask
-//    -VnRGBShaderMask -FhtmpShaderHeader
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
 //
 //
 // Buffer Definitions: 
 //
 // cbuffer $Globals
 // {
 //
 //   float4 fLayerColor;                // Offset:    0 Size:    16 [unused]
@@ -3300,28 +3575,28 @@ const BYTE SolidColorShaderMask[] =
 // 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
+// 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
+// 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)
 //
@@ -3364,20 +3639,20 @@ sample r1.xyzw, v1.zwzz, t3.xyzw, s0
 mov r0.w, cb0[1].x
 mul o0.xyzw, r0.xyzw, r1.xxxx
 ret 
 // Approximately 6 instruction slots used
 #endif
 
 const BYTE RGBShaderMask[] =
 {
-     68,  88,  66,  67,  77,  94, 
-    252, 215, 133,  78, 101, 216, 
-    220,   8,  70, 254,  89, 142, 
-    130, 135,   1,   0,   0,   0, 
+     68,  88,  66,  67, 151, 113, 
+      6, 167,  51, 154, 234, 112, 
+     72, 240,  46, 160, 193, 164, 
+     13, 255,   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, 
@@ -3579,19 +3854,19 @@ const BYTE RGBShaderMask[] =
      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,  50,  57, 
-     46,  57,  53,  50,  46,  51, 
-     49,  49,  49,   0, 171, 171, 
+    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, 
@@ -3611,23 +3886,20 @@ const BYTE RGBShaderMask[] =
       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
 };
+ShaderBytes sRGBShaderMask = { RGBShaderMask, sizeof(RGBShaderMask) };
 #if 0
 //
-// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111
-//
-//
-//   fxc -nologo -Tps_4_0_level_9_3 CompositorD3D11.hlsl -ERGBAShaderMask
-//    -VnRGBAShaderMask -FhtmpShaderHeader
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
 //
 //
 // Buffer Definitions: 
 //
 // cbuffer $Globals
 // {
 //
 //   float4 fLayerColor;                // Offset:    0 Size:    16 [unused]
@@ -3650,28 +3922,28 @@ const BYTE RGBShaderMask[] =
 // 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
+// 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
+// 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)
 //
@@ -3712,20 +3984,20 @@ mul r0.xyzw, r0.xyzw, cb0[1].xxxx
 sample r1.xyzw, v1.zwzz, t3.xyzw, s0
 mul o0.xyzw, r0.xyzw, r1.xxxx
 ret 
 // Approximately 5 instruction slots used
 #endif
 
 const BYTE RGBAShaderMask[] =
 {
-     68,  88,  66,  67, 138,  69, 
-     81, 181, 217,  15, 199,  10, 
-    146, 208, 232, 248,  24,  27, 
-    141,  26,   1,   0,   0,   0, 
+     68,  88,  66,  67, 182, 158, 
+     23,  70, 121, 188, 140, 117, 
+    148, 125,  14, 205, 185, 113, 
+    155,  74,   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, 
@@ -3921,19 +4193,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,  50,  57, 
-     46,  57,  53,  50,  46,  51, 
-     49,  49,  49,   0, 171, 171, 
+    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, 
@@ -3953,23 +4225,372 @@ const BYTE RGBAShaderMask[] =
       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
 };
+ShaderBytes sRGBAShaderMask = { RGBAShaderMask, sizeof(RGBAShaderMask) };
 #if 0
 //
-// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111
-//
-//
-//   fxc -nologo -Tps_4_0_level_9_3 CompositorD3D11.hlsl -ERGBAShaderMask3D
-//    -VnRGBAShaderMask3D -FhtmpShaderHeader
+// 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.x, r1
+    mul r0.xyz, r0.w, r0
+    mov oC0, r0
+
+// approximately 7 instruction slots used (2 texture, 5 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 r0.xyzw, r0.xyzw, r1.xxxx
+mul o0.xyz, r0.wwww, r0.xyzx
+mov o0.w, r0.w
+ret 
+// Approximately 7 instruction slots used
+#endif
+
+const BYTE RGBAShaderMaskPremul[] =
+{
+     68,  88,  66,  67, 170, 142, 
+     83, 183,  24, 153, 194, 125, 
+     42, 169,  16, 185, 222,  43, 
+    161, 111,   1,   0,   0,   0, 
+    220,   5,   0,   0,   6,   0, 
+      0,   0,  56,   0,   0,   0, 
+     12,   1,   0,   0,  60,   2, 
+      0,   0, 184,   2,   0,   0, 
+     56,   5,   0,   0, 168,   5, 
+      0,   0,  65, 111, 110,  57, 
+    204,   0,   0,   0, 204,   0, 
+      0,   0,   0,   2, 255, 255, 
+    148,   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,   0, 128,   1,   0, 
+    228, 128,   5,   0,   0,   3, 
+      0,   0,   7, 128,   0,   0, 
+    255, 128,   0,   0, 228, 128, 
+      1,   0,   0,   2,   0,   8, 
+     15, 128,   0,   0, 228, 128, 
+    255, 255,   0,   0,  83,  72, 
+     68,  82,  40,   1,   0,   0, 
+     64,   0,   0,   0,  74,   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,   0, 
+     16,   0,   0,   0,   0,   0, 
+     70,  14,  16,   0,   0,   0, 
+      0,   0,   6,   0,  16,   0, 
+      1,   0,   0,   0,  56,   0, 
+      0,   7, 114,  32,  16,   0, 
+      0,   0,   0,   0, 246,  15, 
+     16,   0,   0,   0,   0,   0, 
+     70,   2,  16,   0,   0,   0, 
+      0,   0,  54,   0,   0,   5, 
+    130,  32,  16,   0,   0,   0, 
+      0,   0,  58,   0,  16,   0, 
+      0,   0,   0,   0,  62,   0, 
+      0,   1,  83,  84,  65,  84, 
+    116,   0,   0,   0,   7,   0, 
+      0,   0,   2,   0,   0,   0, 
+      0,   0,   0,   0,   3,   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, 
+      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, 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
+};
+ShaderBytes sRGBAShaderMaskPremul = { RGBAShaderMaskPremul, sizeof(RGBAShaderMaskPremul) };
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
 //
 //
 // Buffer Definitions: 
 //
 // cbuffer $Globals
 // {
 //
 //   float4 fLayerColor;                // Offset:    0 Size:    16 [unused]
@@ -3993,28 +4614,28 @@ const BYTE RGBAShaderMask[] =
 // 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   xyz         2     NONE  float   xyz 
+// Name                 Index   Mask Register SysValue  Format   Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_Position              0   xyzw        0      POS   float       
+// TEXCOORD                 0   xy          1     NONE   float   xy  
+// TEXCOORD                 1   xyz         2     NONE   float   xyz 
 //
 //
 // Output signature:
 //
-// Name                 Index   Mask Register SysValue Format   Used
-// -------------------- ----- ------ -------- -------- ------ ------
-// SV_Target                0   xyzw        0   TARGET  float   xyzw
+// 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)
 //
@@ -4059,20 +4680,20 @@ sample r1.xyzw, v1.xyxx, t0.xyzw, s0
 mul r1.xyzw, r1.xyzw, cb0[1].xxxx
 mul o0.xyzw, r0.xxxx, r1.xyzw
 ret 
 // Approximately 6 instruction slots used
 #endif
 
 const BYTE RGBAShaderMask3D[] =
 {
-     68,  88,  66,  67,   4, 135, 
-     55,   9, 144, 137,  25,  77, 
-     92, 150, 209,   2,  32, 225, 
-     75, 182,   1,   0,   0,   0, 
+     68,  88,  66,  67, 216,  42, 
+    250, 215, 154,  11,  43,  24, 
+     15, 254,  10,  66,  72, 210, 
+    238, 215,   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, 
@@ -4289,19 +4910,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,  50,  57,  46,  57, 
-     53,  50,  46,  51,  49,  49, 
-     49,   0, 171, 171,  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, 
@@ -4320,23 +4941,398 @@ const BYTE RGBAShaderMask3D[] =
       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
 };
+ShaderBytes sRGBAShaderMask3D = { RGBAShaderMask3D, sizeof(RGBAShaderMask3D) };
 #if 0
 //
-// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111
-//
-//
-//   fxc -nologo -Tps_4_0_level_9_3 CompositorD3D11.hlsl -EYCbCrShaderMask
-//    -VnYCbCrShaderMask -FhtmpShaderHeader
+// 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
+// LayerTextureSamplerLinear         sampler      NA          NA    1        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   xyz         2     NONE   float   xyz 
+//
+//
+// 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               
+// s1             s1              t3               
+//
+//
+// Level9 shader bytecode:
+//
+    ps_2_x
+    dcl t0.xy
+    dcl t1.xyz
+    dcl_2d s0
+    dcl_2d s1
+    rcp r0.w, t1.z
+    mul r0.xy, r0.w, t1
+    texld r1, t0, s0
+    texld r0, r0, s1
+    mul r1, r1, c0.x
+    mul r0, r0.x, r1
+    mul r0.xyz, r0.w, r0
+    mov oC0, r0
+
+// approximately 8 instruction slots used (2 texture, 6 arithmetic)
+ps_4_0
+dcl_constantbuffer cb0[2], immediateIndexed
+dcl_sampler s0, mode_default
+dcl_sampler s1, 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 v2.xyz
+dcl_output o0.xyzw
+dcl_temps 2
+div r0.xy, v2.xyxx, v2.zzzz
+sample r0.xyzw, r0.xyxx, t3.xyzw, s1
+sample r1.xyzw, v1.xyxx, t0.xyzw, s0
+mul r1.xyzw, r1.xyzw, cb0[1].xxxx
+mul r0.xyzw, r0.xxxx, r1.xyzw
+mul o0.xyz, r0.wwww, r0.xyzx
+mov o0.w, r0.w
+ret 
+// Approximately 8 instruction slots used
+#endif
+
+const BYTE RGBAShaderMask3DPremul[] =
+{
+     68,  88,  66,  67,  55,   2, 
+    221,  89,  65,  95,  19,  52, 
+    117,  31,  78, 231,   8,  20, 
+    150,  44,   1,   0,   0,   0, 
+     88,   6,   0,   0,   6,   0, 
+      0,   0,  56,   0,   0,   0, 
+     40,   1,   0,   0, 128,   2, 
+      0,   0, 252,   2,   0,   0, 
+    180,   5,   0,   0,  36,   6, 
+      0,   0,  65, 111, 110,  57, 
+    232,   0,   0,   0, 232,   0, 
+      0,   0,   0,   2, 255, 255, 
+    176,   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,   0,   0, 
+      0,   0,   3,   1,   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,   3, 176,  31,   0, 
+      0,   2,   0,   0,   0, 128, 
+      1,   0,   7, 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,   6,   0, 
+      0,   2,   0,   0,   8, 128, 
+      1,   0, 170, 176,   5,   0, 
+      0,   3,   0,   0,   3, 128, 
+      0,   0, 255, 128,   1,   0, 
+    228, 176,  66,   0,   0,   3, 
+      1,   0,  15, 128,   0,   0, 
+    228, 176,   0,   8, 228, 160, 
+     66,   0,   0,   3,   0,   0, 
+     15, 128,   0,   0, 228, 128, 
+      1,   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, 
+      0, 128,   1,   0, 228, 128, 
+      5,   0,   0,   3,   0,   0, 
+      7, 128,   0,   0, 255, 128, 
+      0,   0, 228, 128,   1,   0, 
+      0,   2,   0,   8,  15, 128, 
+      0,   0, 228, 128, 255, 255, 
+      0,   0,  83,  72,  68,  82, 
+     80,   1,   0,   0,  64,   0, 
+      0,   0,  84,   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,  90,   0, 
+      0,   3,   0,  96,  16,   0, 
+      1,   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, 114,  16, 
+     16,   0,   2,   0,   0,   0, 
+    101,   0,   0,   3, 242,  32, 
+     16,   0,   0,   0,   0,   0, 
+    104,   0,   0,   2,   2,   0, 
+      0,   0,  14,   0,   0,   7, 
+     50,   0,  16,   0,   0,   0, 
+      0,   0,  70,  16,  16,   0, 
+      2,   0,   0,   0, 166,  26, 
+     16,   0,   2,   0,   0,   0, 
+     69,   0,   0,   9, 242,   0, 
+     16,   0,   0,   0,   0,   0, 
+     70,   0,  16,   0,   0,   0, 
+      0,   0,  70, 126,  16,   0, 
+      3,   0,   0,   0,   0,  96, 
+     16,   0,   1,   0,   0,   0, 
+     69,   0,   0,   9, 242,   0, 
+     16,   0,   1,   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,   1,   0,   0,   0, 
+     70,  14,  16,   0,   1,   0, 
+      0,   0,   6, 128,  32,   0, 
+      0,   0,   0,   0,   1,   0, 
+      0,   0,  56,   0,   0,   7, 
+    242,   0,  16,   0,   0,   0, 
+      0,   0,   6,   0,  16,   0, 
+      0,   0,   0,   0,  70,  14, 
+     16,   0,   1,   0,   0,   0, 
+     56,   0,   0,   7, 114,  32, 
+     16,   0,   0,   0,   0,   0, 
+    246,  15,  16,   0,   0,   0, 
+      0,   0,  70,   2,  16,   0, 
+      0,   0,   0,   0,  54,   0, 
+      0,   5, 130,  32,  16,   0, 
+      0,   0,   0,   0,  58,   0, 
+     16,   0,   0,   0,   0,   0, 
+     62,   0,   0,   1,  83,  84, 
+     65,  84, 116,   0,   0,   0, 
+      8,   0,   0,   0,   2,   0, 
+      0,   0,   0,   0,   0,   0, 
+      3,   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,   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, 
+    176,   2,   0,   0,   1,   0, 
+      0,   0, 244,   0,   0,   0, 
+      5,   0,   0,   0,  28,   0, 
+      0,   0,   0,   4, 255, 255, 
+      0,   1,   0,   0, 125,   2, 
+      0,   0, 188,   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, 197,   0, 
+      0,   0,   3,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      1,   0,   0,   0,   1,   0, 
+      0,   0,   0,   0,   0,   0, 
+    223,   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, 228,   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, 234,   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,  76,  97, 121, 
+    101, 114,  84, 101, 120, 116, 
+    117, 114, 101,  83,  97, 109, 
+    112, 108, 101, 114,  76, 105, 
+    110, 101,  97, 114,   0, 116, 
+     82,  71,  66,   0, 116,  77, 
+     97, 115, 107,   0,  36,  71, 
+    108, 111,  98,  97, 108, 115, 
+      0, 171, 234,   0,   0,   0, 
+      8,   0,   0,   0,  12,   1, 
+      0,   0, 224,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0, 204,   1,   0,   0, 
+      0,   0,   0,   0,  16,   0, 
+      0,   0,   0,   0,   0,   0, 
+    216,   1,   0,   0,   0,   0, 
+      0,   0, 232,   1,   0,   0, 
+     16,   0,   0,   0,   4,   0, 
+      0,   0,   2,   0,   0,   0, 
+    248,   1,   0,   0,   0,   0, 
+      0,   0,   8,   2,   0,   0, 
+     32,   0,   0,   0,  64,   0, 
+      0,   0,   0,   0,   0,   0, 
+     24,   2,   0,   0,   0,   0, 
+      0,   0,  40,   2,   0,   0, 
+     96,   0,   0,   0,  64,   0, 
+      0,   0,   0,   0,   0,   0, 
+     24,   2,   0,   0,   0,   0, 
+      0,   0,  52,   2,   0,   0, 
+    160,   0,   0,   0,  16,   0, 
+      0,   0,   0,   0,   0,   0, 
+    216,   1,   0,   0,   0,   0, 
+      0,   0,  72,   2,   0,   0, 
+    176,   0,   0,   0,  16,   0, 
+      0,   0,   0,   0,   0,   0, 
+     88,   2,   0,   0,   0,   0, 
+      0,   0, 104,   2,   0,   0, 
+    192,   0,   0,   0,  16,   0, 
+      0,   0,   0,   0,   0,   0, 
+     88,   2,   0,   0,   0,   0, 
+      0,   0, 115,   2,   0,   0, 
+    208,   0,   0,   0,  16,   0, 
+      0,   0,   0,   0,   0,   0, 
+     88,   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,   2,   0, 
+      0,   0,   7,   7,   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
+};
+ShaderBytes sRGBAShaderMask3DPremul = { RGBAShaderMask3DPremul, sizeof(RGBAShaderMask3DPremul) };
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
 //
 //
 // Buffer Definitions: 
 //
 // cbuffer $Globals
 // {
 //
 //   float4 fLayerColor;                // Offset:    0 Size:    16 [unused]
@@ -4361,28 +5357,28 @@ const BYTE RGBAShaderMask3D[] =
 // tCr                               texture  float4          2d    2        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
+// 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
+// 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)
 //
@@ -4455,20 +5451,20 @@ mul r0.xyzw, r1.xyzw, cb0[1].xxxx
 sample r1.xyzw, v1.zwzz, t3.xyzw, s0
 mul o0.xyzw, r0.xyzw, r1.xxxx
 ret 
 // Approximately 17 instruction slots used
 #endif
 
 const BYTE YCbCrShaderMask[] =
 {
-     68,  88,  66,  67,  74,  33, 
-    155, 235,  22, 178,  84, 169, 
-    113,  91, 240,  98, 157, 143, 
-    221,  19,   1,   0,   0,   0, 
+     68,  88,  66,  67, 154,  30, 
+    246, 171,  67, 224, 184,  33, 
+     20, 150, 106, 233, 226, 126, 
+     80, 130,   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, 
@@ -4662,17 +5658,17 @@ const BYTE YCbCrShaderMask[] =
      16,   0,   0,   0,   0,   0, 
      70,  14,  16,   0,   0,   0, 
       0,   0,   6,   0,  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, 
@@ -4794,19 +5790,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,  50,  57, 
-     46,  57,  53,  50,  46,  51, 
-     49,  49,  49,   0, 171, 171, 
+    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, 
@@ -4826,24 +5822,20 @@ const BYTE YCbCrShaderMask[] =
       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
 };
+ShaderBytes sYCbCrShaderMask = { YCbCrShaderMask, sizeof(YCbCrShaderMask) };
 #if 0
 //
-// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111
-//
-//
-//   fxc -nologo -Tps_4_0_level_9_3 CompositorD3D11.hlsl
-//    -EComponentAlphaShaderMask -VnComponentAlphaShaderMask
-//    -FhtmpShaderHeader
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
 //
 //
 // Buffer Definitions: 
 //
 // cbuffer $Globals
 // {
 //
 //   float4 fLayerColor;                // Offset:    0 Size:    16 [unused]
@@ -4867,29 +5859,29 @@ const BYTE YCbCrShaderMask[] =
 // tRGBWhite                         texture  float4          2d    1        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
+// 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
-// SV_Target                1   xyzw        1   TARGET  float   xyzw
+// Name                 Index   Mask Register SysValue  Format   Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_Target                0   xyzw        0   TARGET   float   xyzw
+// SV_Target                1   xyzw        1   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)
 //
@@ -4946,20 +5938,20 @@ mul r2.x, r2.x, 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, 214,  67, 
-    206,  69,  12, 117, 144,  46, 
-    127, 133, 145, 240,  56, 186, 
-    119, 195,   1,   0,   0,   0, 
+     68,  88,  66,  67, 102,   2, 
+     84, 222,  33, 141, 105, 188, 
+    152,  82,  64, 100,  57, 101, 
+    192, 110,   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, 
@@ -5096,17 +6088,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,   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, 
     160,   2,   0,   0,   1,   0, 
@@ -5214,19 +6206,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,  50,  57,  46,  57, 
-     53,  50,  46,  51,  49,  49, 
-     49,   0, 171, 171,  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, 
@@ -5249,8 +6241,9 @@ const BYTE ComponentAlphaShaderMask[] =
       0,   0,  15,   0,   0,   0, 
      56,   0,   0,   0,   1,   0, 
       0,   0,   0,   0,   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
 };
+ShaderBytes sComponentAlphaShaderMask = { ComponentAlphaShaderMask, sizeof(ComponentAlphaShaderMask) };
--- a/gfx/layers/d3d11/CompositorD3D11ShadersVR.h
+++ b/gfx/layers/d3d11/CompositorD3D11ShadersVR.h
@@ -1,15 +1,11 @@
 #if 0
 //
-// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111
-//
-//
-//   fxc -nologo -Tvs_4_0_level_9_3 CompositorD3D11VR.hlsl
-//    -EOculusVRDistortionVS -VnOculusVRDistortionVS -FhtmpShaderHeader
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
 //
 //
 // Buffer Definitions: 
 //
 // cbuffer $Globals
 // {
 //
 //   float4 VREyeToSource;              // Offset:    0 Size:    16
@@ -23,34 +19,34 @@
 // 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
+// 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
+// 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)
 //
@@ -105,20 +101,20 @@ mad o3.xy, v3.xyxx, cb0[0].zwzz, cb0[0].
 mov o3.z, l(1.000000)
 mov o4.xyzw, v4.xyzw
 ret 
 // Approximately 10 instruction slots used
 #endif
 
 const BYTE Oculus050VRDistortionVS[] =
 {
-     68,  88,  66,  67, 206, 154, 
-    203,  64, 121,  47, 121, 169, 
-    222, 206, 108, 175, 167, 227, 
-    154,  37,   1,   0,   0,   0, 
+     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, 
@@ -244,17 +240,17 @@ const BYTE Oculus050VRDistortionVS[] =
     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,   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, 
@@ -302,19 +298,19 @@ const BYTE Oculus050VRDistortionVS[] =
      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,  50,  57,  46, 
-     57,  53,  50,  46,  51,  49, 
-     49,  49,   0, 171, 171, 171, 
+     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, 
@@ -360,50 +356,47 @@ const BYTE Oculus050VRDistortionVS[] =
       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
 };
+ShaderBytes sOculus050VRDistortionVS = { Oculus050VRDistortionVS, sizeof(Oculus050VRDistortionVS) };
 #if 0
 //
-// Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111
-//
-//
-//   fxc -nologo -Tps_4_0_level_9_3 CompositorD3D11VR.hlsl
-//    -EOculusVRDistortionPS -VnOculusVRDistortionPS -FhtmpShaderHeader
+// 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   
+// 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
+// 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               
 //
@@ -444,25 +437,25 @@ 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 Oculus050VRDistortionPS[] =
 {
-     68,  88,  66,  67,  48, 161, 
-    127, 216, 149, 107,  53,  57, 
-    164,  84,  84, 154,  58, 227, 
-    125,  61,   1,   0,   0,   0, 
-    124,   4,   0,   0,   6,   0, 
+     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, 
-    164,   3,   0,   0,  72,   4, 
+    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, 
@@ -572,17 +565,17 @@ const BYTE Oculus050VRDistortionPS[] =
       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, 156,   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, 
@@ -597,48 +590,49 @@ const BYTE Oculus050VRDistortionPS[] =
     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,  50,  57,  46,  57, 
-     53,  50,  46,  51,  49,  49, 
-     49,   0,  73,  83,  71,  78, 
-    156,   0,   0,   0,   5,   0, 
+     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, 
-    128,   0,   0,   0,   0,   0, 
-      0,   0,   1,   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, 
-    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
+     83,  86,  95,  84,  97, 114, 
+    103, 101, 116,   0, 171, 171
 };
+ShaderBytes sOculus050VRDistortionPS = { Oculus050VRDistortionPS, sizeof(Oculus050VRDistortionPS) };
--- a/gfx/layers/d3d11/genshaders.sh
+++ b/gfx/layers/d3d11/genshaders.sh
@@ -9,40 +9,46 @@ FXC_FLAGS=""
 
 # If DEBUG is in the environment, then rebuild with debug info
 if [ "$DEBUG" != "" ] ; then
   FXC_FLAGS="$FXC_DEBUG_FLAGS"
 fi
 
 makeShaderVS() {
     fxc -nologo $FXC_FLAGS -Tvs_4_0_level_9_3 $SRC -E$1 -Vn$1 -Fh$tempfile
+    echo "ShaderBytes s$1 = { $1, sizeof($1) };" >> $tempfile;
     cat $tempfile >> $DEST
 }
 
 makeShaderPS() {
     fxc -nologo $FXC_FLAGS -Tps_4_0_level_9_3 $SRC -E$1 -Vn$1 -Fh$tempfile
+    echo "ShaderBytes s$1 = { $1, sizeof($1) };" >> $tempfile;
     cat $tempfile >> $DEST
 }
 
 SRC=CompositorD3D11.hlsl
 DEST=CompositorD3D11Shaders.h
 
 rm -f $DEST
+echo "struct ShaderBytes { const void* mData; size_t mLength; };" >> $DEST;
 makeShaderVS LayerQuadVS
 makeShaderPS SolidColorShader
 makeShaderPS RGBShader
 makeShaderPS RGBAShader
+makeShaderPS RGBAShaderPremul
 makeShaderPS ComponentAlphaShader
 makeShaderPS YCbCrShader
 makeShaderVS LayerQuadMaskVS
 makeShaderVS LayerQuadMask3DVS
 makeShaderPS SolidColorShaderMask
 makeShaderPS RGBShaderMask
 makeShaderPS RGBAShaderMask
+makeShaderPS RGBAShaderMaskPremul
 makeShaderPS RGBAShaderMask3D
+makeShaderPS RGBAShaderMask3DPremul
 makeShaderPS YCbCrShaderMask
 makeShaderPS ComponentAlphaShaderMask
 
 SRC=CompositorD3D11VR.hlsl
 DEST=CompositorD3D11ShadersVR.h
 
 rm -f $DEST
 makeShaderVS Oculus050VRDistortionVS
--- a/gfx/thebes/SoftwareVsyncSource.cpp
+++ b/gfx/thebes/SoftwareVsyncSource.cpp
@@ -1,16 +1,17 @@
 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  * 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 "SoftwareVsyncSource.h"
 #include "base/task.h"
+#include "gfxPlatform.h"
 #include "nsThreadUtils.h"
 
 SoftwareVsyncSource::SoftwareVsyncSource()
 {
   MOZ_ASSERT(NS_IsMainThread());
   mGlobalDisplay = new SoftwareDisplay();
 }
 
@@ -22,17 +23,17 @@ SoftwareVsyncSource::~SoftwareVsyncSourc
 }
 
 SoftwareDisplay::SoftwareDisplay()
   : mCurrentVsyncTask(nullptr)
   , mVsyncEnabled(false)
 {
   // Mimic 60 fps
   MOZ_ASSERT(NS_IsMainThread());
-  const double rate = 1000 / 60.0;
+  const double rate = 1000.0 / (double) gfxPlatform::GetSoftwareVsyncRate();
   mVsyncRate = mozilla::TimeDuration::FromMilliseconds(rate);
   mVsyncThread = new base::Thread("SoftwareVsyncThread");
   MOZ_RELEASE_ASSERT(mVsyncThread->Start(), "Could not start software vsync thread");
 }
 
 SoftwareDisplay::~SoftwareDisplay() {}
 
 void
--- a/gfx/thebes/gfxPlatform.cpp
+++ b/gfx/thebes/gfxPlatform.cpp
@@ -576,17 +576,21 @@ gfxPlatform::Init()
     nsCOMPtr<imgITools> imgTools = do_GetService("@mozilla.org/image/tools;1");
     if (!imgTools) {
       NS_RUNTIMEABORT("Could not initialize ImageLib");
     }
 
     RegisterStrongMemoryReporter(new GfxMemoryImageReporter());
 
     if (XRE_IsParentProcess()) {
-      gPlatform->mVsyncSource = gPlatform->CreateHardwareVsyncSource();
+      if (gfxPlatform::ForceSoftwareVsync()) {
+        gPlatform->mVsyncSource = (gPlatform)->gfxPlatform::CreateHardwareVsyncSource();
+      } else {
+        gPlatform->mVsyncSource = gPlatform->CreateHardwareVsyncSource();
+      }
     }
 }
 
 static bool sLayersIPCIsUp = false;
 
 void
 gfxPlatform::Shutdown()
 {
@@ -2323,16 +2327,23 @@ gfxPlatform::UsesOffMainThreadCompositin
 
 #endif
     firstTime = false;
   }
 
   return result;
 }
 
+/***
+ * The preference "layout.frame_rate" has 3 meanings depending on the value:
+ *
+ * -1 = Auto (default), use hardware vsync or software vsync @ 60 hz if hw vsync fails.
+ *  0 = ASAP mode - used during talos testing.
+ *  X = Software vsync at a rate of X times per second.
+ */
 already_AddRefed<mozilla::gfx::VsyncSource>
 gfxPlatform::CreateHardwareVsyncSource()
 {
   NS_WARNING("Hardware Vsync support not yet implemented. Falling back to software timers");
   nsRefPtr<mozilla::gfx::VsyncSource> softwareVsync = new SoftwareVsyncSource();
   return softwareVsync.forget();
 }
 
@@ -2342,16 +2353,39 @@ gfxPlatform::IsInLayoutAsapMode()
   // There are 2 modes of ASAP mode.
   // 1 is that the refresh driver and compositor are in lock step
   // the second is that the compositor goes ASAP and the refresh driver
   // goes at whatever the configurated rate is. This only checks the version
   // talos uses, which is the refresh driver and compositor are in lockstep.
   return Preferences::GetInt("layout.frame_rate", -1) == 0;
 }
 
+/* static */ bool
+gfxPlatform::ForceSoftwareVsync()
+{
+  return Preferences::GetInt("layout.frame_rate", -1) > 0;
+}
+
+/* static */ int
+gfxPlatform::GetSoftwareVsyncRate()
+{
+  int preferenceRate = Preferences::GetInt("layout.frame_rate",
+                                           gfxPlatform::GetDefaultFrameRate());
+  if (preferenceRate <= 0) {
+    return gfxPlatform::GetDefaultFrameRate();
+  }
+  return preferenceRate;
+}
+
+/* static */ int
+gfxPlatform::GetDefaultFrameRate()
+{
+  return 60;
+}
+
 static nsString
 DetectBadApzWheelInputPrefs()
 {
   static const char *sBadMultiplierPrefs[] = {
     "mousewheel.default.delta_multiplier_x",
     "mousewheel.with_alt.delta_multiplier_x",
     "mousewheel.with_control.delta_multiplier_x",
     "mousewheel.with_meta.delta_multiplier_x",
--- a/gfx/thebes/gfxPlatform.h
+++ b/gfx/thebes/gfxPlatform.h
@@ -603,16 +603,31 @@ public:
     /**
      * True if layout rendering should use ASAP mode, which means
      * the refresh driver and compositor should render ASAP.
      * Used for talos testing purposes
      */
     static bool IsInLayoutAsapMode();
 
     /**
+     * Returns the software vsync rate to use.
+     */
+    static int GetSoftwareVsyncRate();
+
+    /**
+     * Returns whether or not a custom vsync rate is set.
+     */
+    static bool ForceSoftwareVsync();
+
+    /**
+     * Returns the default frame rate for the refresh driver / software vsync.
+     */
+    static int GetDefaultFrameRate();
+
+    /**
      * Used to test which input types are handled via APZ.
      */
     virtual bool SupportsApzWheelInput() const {
       return false;
     }
     virtual bool SupportsApzTouchInput() const {
       return false;
     }
--- a/js/src/jit-test/tests/ion/bug1107011-2.js
+++ b/js/src/jit-test/tests/ion/bug1107011-2.js
@@ -3,10 +3,10 @@ function foo() {
     function bar() {
         x = y;
         y = a[0];
     }
     for (var i = 0; i < 1000; i++) {
         bar();
     }
 }
-for (var i=0; i<10000; i++)
+for (var i=0; i < 50; i++)
     foo();
--- a/js/src/jit/arm/CodeGenerator-arm.cpp
+++ b/js/src/jit/arm/CodeGenerator-arm.cpp
@@ -2445,42 +2445,59 @@ CodeGeneratorARM::visitUDiv(LUDiv* ins)
     Register rhs = ToRegister(ins->rhs());
     Register output = ToRegister(ins->output());
 
     Label done;
     generateUDivModZeroCheck(rhs, output, &done, ins->snapshot(), ins->mir());
 
     masm.ma_udiv(lhs, rhs, output);
 
+    // Check for large unsigned result - represent as double.
     if (!ins->mir()->isTruncated()) {
+        MOZ_ASSERT(ins->mir()->fallible());
         masm.ma_cmp(output, Imm32(0));
         bailoutIf(Assembler::LessThan, ins->snapshot());
     }
 
-    masm.bind(&done);
+    // Check for non-zero remainder if not truncating to int.
+    if (!ins->mir()->canTruncateRemainder()) {
+        MOZ_ASSERT(ins->mir()->fallible());
+        {
+            ScratchRegisterScope scratch(masm);
+            masm.ma_mul(rhs, output, scratch);
+            masm.ma_cmp(scratch, lhs);
+        }
+        bailoutIf(Assembler::NotEqual, ins->snapshot());
+    }
+
+    if (done.used())
+        masm.bind(&done);
 }
 
 void
 CodeGeneratorARM::visitUMod(LUMod* ins)
 {
     Register lhs = ToRegister(ins->lhs());
     Register rhs = ToRegister(ins->rhs());
     Register output = ToRegister(ins->output());
 
     Label done;
     generateUDivModZeroCheck(rhs, output, &done, ins->snapshot(), ins->mir());
 
     masm.ma_umod(lhs, rhs, output);
 
+    // Check for large unsigned result - represent as double.
     if (!ins->mir()->isTruncated()) {
+        MOZ_ASSERT(ins->mir()->fallible());
         masm.ma_cmp(output, Imm32(0));
         bailoutIf(Assembler::LessThan, ins->snapshot());
     }
 
-    masm.bind(&done);
+    if (done.used())
+        masm.bind(&done);
 }
 
 template<class T>
 void
 CodeGeneratorARM::generateUDivModZeroCheck(Register rhs, Register output, Label* done,
                                            LSnapshot* snapshot, T* mir)
 {
     if (!mir)
copy from js/src/jit/mips32/Lowering-mips32.cpp
copy to js/src/jit/mips-shared/Lowering-mips-shared.cpp
--- a/js/src/jit/mips32/Lowering-mips32.cpp
+++ b/js/src/jit/mips-shared/Lowering-mips-shared.cpp
@@ -1,249 +1,107 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  * vim: set ts=8 sts=4 et sw=4 tw=99:
  * 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 "jit/mips-shared/Lowering-mips-shared.h"
+
 #include "mozilla/MathAlgorithms.h"
 
-
-#include "jit/Lowering.h"
-#include "jit/mips32/Assembler-mips32.h"
 #include "jit/MIR.h"
 
 #include "jit/shared/Lowering-shared-inl.h"
 
 using namespace js;
 using namespace js::jit;
 
 using mozilla::FloorLog2;
 
-void
-LIRGeneratorMIPS::useBoxFixed(LInstruction* lir, size_t n, MDefinition* mir, Register reg1,
-                              Register reg2, bool useAtStart)
-{
-    MOZ_ASSERT(mir->type() == MIRType_Value);
-    MOZ_ASSERT(reg1 != reg2);
-
-    ensureDefined(mir);
-    lir->setOperand(n, LUse(reg1, mir->virtualRegister(), useAtStart));
-    lir->setOperand(n + 1, LUse(reg2, VirtualRegisterOfPayload(mir), useAtStart));
-}
-
 LAllocation
-LIRGeneratorMIPS::useByteOpRegister(MDefinition* mir)
+LIRGeneratorMIPSShared::useByteOpRegister(MDefinition* mir)
 {
     return useRegister(mir);
 }
 
 LAllocation
-LIRGeneratorMIPS::useByteOpRegisterOrNonDoubleConstant(MDefinition* mir)
+LIRGeneratorMIPSShared::useByteOpRegisterOrNonDoubleConstant(MDefinition* mir)
 {
     return useRegisterOrNonDoubleConstant(mir);
 }
 
 LDefinition
-LIRGeneratorMIPS::tempByteOpRegister()
+LIRGeneratorMIPSShared::tempByteOpRegister()
 {
     return temp();
 }
 
-void
-LIRGeneratorMIPS::visitBox(MBox* box)
-{
-    MDefinition* inner = box->getOperand(0);
-
-    // If the box wrapped a double, it needs a new register.
-    if (IsFloatingPointType(inner->type())) {
-        defineBox(new(alloc()) LBoxFloatingPoint(useRegisterAtStart(inner),
-                                                 tempCopy(inner, 0), inner->type()), box);
-        return;
-    }
-
-    if (box->canEmitAtUses()) {
-        emitAtUses(box);
-        return;
-    }
-
-    if (inner->isConstant()) {
-        defineBox(new(alloc()) LValue(inner->toConstant()->value()), box);
-        return;
-    }
-
-    LBox* lir = new(alloc()) LBox(use(inner), inner->type());
-
-    // Otherwise, we should not define a new register for the payload portion
-    // of the output, so bypass defineBox().
-    uint32_t vreg = getVirtualRegister();
-
-    // Note that because we're using BogusTemp(), we do not change the type of
-    // the definition. We also do not define the first output as "TYPE",
-    // because it has no corresponding payload at (vreg + 1). Also note that
-    // although we copy the input's original type for the payload half of the
-    // definition, this is only for clarity. BogusTemp() definitions are
-    // ignored.
-    lir->setDef(0, LDefinition(vreg, LDefinition::GENERAL));
-    lir->setDef(1, LDefinition::BogusTemp());
-    box->setVirtualRegister(vreg);
-    add(lir);
-}
-
-void
-LIRGeneratorMIPS::visitUnbox(MUnbox* unbox)
-{
-    MDefinition* inner = unbox->getOperand(0);
-
-    if (inner->type() == MIRType_ObjectOrNull) {
-        LUnboxObjectOrNull* lir = new(alloc()) LUnboxObjectOrNull(useRegisterAtStart(inner));
-        if (unbox->fallible())
-            assignSnapshot(lir, unbox->bailoutKind());
-        defineReuseInput(lir, unbox, 0);
-        return;
-    }
-
-    // An unbox on mips reads in a type tag (either in memory or a register) and
-    // a payload. Unlike most instructions consuming a box, we ask for the type
-    // second, so that the result can re-use the first input.
-    MOZ_ASSERT(inner->type() == MIRType_Value);
-
-    ensureDefined(inner);
-
-    if (IsFloatingPointType(unbox->type())) {
-        LUnboxFloatingPoint* lir = new(alloc()) LUnboxFloatingPoint(unbox->type());
-        if (unbox->fallible())
-            assignSnapshot(lir, unbox->bailoutKind());
-        useBox(lir, LUnboxFloatingPoint::Input, inner);
-        define(lir, unbox);
-        return;
-    }
-
-    // Swap the order we use the box pieces so we can re-use the payload
-    // register.
-    LUnbox* lir = new(alloc()) LUnbox;
-    lir->setOperand(0, usePayloadInRegisterAtStart(inner));
-    lir->setOperand(1, useType(inner, LUse::REGISTER));
-
-    if (unbox->fallible())
-        assignSnapshot(lir, unbox->bailoutKind());
-
-    // Types and payloads form two separate intervals. If the type becomes dead
-    // before the payload, it could be used as a Value without the type being
-    // recoverable. Unbox's purpose is to eagerly kill the definition of a type
-    // tag, so keeping both alive (for the purpose of gcmaps) is unappealing.
-    // Instead, we create a new virtual register.
-    defineReuseInput(lir, unbox, 0);
-}
-
-void
-LIRGeneratorMIPS::visitReturn(MReturn* ret)
-{
-    MDefinition* opd = ret->getOperand(0);
-    MOZ_ASSERT(opd->type() == MIRType_Value);
-
-    LReturn* ins = new(alloc()) LReturn;
-    ins->setOperand(0, LUse(JSReturnReg_Type));
-    ins->setOperand(1, LUse(JSReturnReg_Data));
-    fillBoxUses(ins, 0, opd);
-    add(ins);
-}
-
 // x = !y
 void
-LIRGeneratorMIPS::lowerForALU(LInstructionHelper<1, 1, 0>* ins,
-                              MDefinition* mir, MDefinition* input)
+LIRGeneratorMIPSShared::lowerForALU(LInstructionHelper<1, 1, 0>* ins,
+                                    MDefinition* mir, MDefinition* input)
 {
     ins->setOperand(0, useRegister(input));
     define(ins, mir, LDefinition(LDefinition::TypeFrom(mir->type()), LDefinition::REGISTER));
 }
 
 // z = x+y
 void
-LIRGeneratorMIPS::lowerForALU(LInstructionHelper<1, 2, 0>* ins, MDefinition* mir,
-                              MDefinition* lhs, MDefinition* rhs)
+LIRGeneratorMIPSShared::lowerForALU(LInstructionHelper<1, 2, 0>* ins, MDefinition* mir,
+                                    MDefinition* lhs, MDefinition* rhs)
 {
     ins->setOperand(0, useRegister(lhs));
     ins->setOperand(1, useRegisterOrConstant(rhs));
     define(ins, mir, LDefinition(LDefinition::TypeFrom(mir->type()), LDefinition::REGISTER));
 }
 
 void
-LIRGeneratorMIPS::lowerForFPU(LInstructionHelper<1, 1, 0>* ins, MDefinition* mir,
-                              MDefinition* input)
+LIRGeneratorMIPSShared::lowerForFPU(LInstructionHelper<1, 1, 0>* ins, MDefinition* mir,
+                                    MDefinition* input)
 {
     ins->setOperand(0, useRegister(input));
     define(ins, mir, LDefinition(LDefinition::TypeFrom(mir->type()), LDefinition::REGISTER));
 }
 
 template<size_t Temps>
 void
-LIRGeneratorMIPS::lowerForFPU(LInstructionHelper<1, 2, Temps>* ins, MDefinition* mir,
-                              MDefinition* lhs, MDefinition* rhs)
+LIRGeneratorMIPSShared::lowerForFPU(LInstructionHelper<1, 2, Temps>* ins, MDefinition* mir,
+                                    MDefinition* lhs, MDefinition* rhs)
 {
     ins->setOperand(0, useRegister(lhs));
     ins->setOperand(1, useRegister(rhs));
     define(ins, mir, LDefinition(LDefinition::TypeFrom(mir->type()), LDefinition::REGISTER));
 }
 
-template void LIRGeneratorMIPS::lowerForFPU(LInstructionHelper<1, 2, 0>* ins, MDefinition* mir,
-                                            MDefinition* lhs, MDefinition* rhs);
-template void LIRGeneratorMIPS::lowerForFPU(LInstructionHelper<1, 2, 1>* ins, MDefinition* mir,
-                                            MDefinition* lhs, MDefinition* rhs);
+template void LIRGeneratorMIPSShared::lowerForFPU(LInstructionHelper<1, 2, 0>* ins, MDefinition* mir,
+                                                  MDefinition* lhs, MDefinition* rhs);
+template void LIRGeneratorMIPSShared::lowerForFPU(LInstructionHelper<1, 2, 1>* ins, MDefinition* mir,
+                                                  MDefinition* lhs, MDefinition* rhs);
 
 void
-LIRGeneratorMIPS::lowerForBitAndAndBranch(LBitAndAndBranch* baab, MInstruction* mir,
-                                          MDefinition* lhs, MDefinition* rhs)
+LIRGeneratorMIPSShared::lowerForBitAndAndBranch(LBitAndAndBranch* baab, MInstruction* mir,
+                                                MDefinition* lhs, MDefinition* rhs)
 {
     baab->setOperand(0, useRegisterAtStart(lhs));
     baab->setOperand(1, useRegisterOrConstantAtStart(rhs));
     add(baab, mir);
 }
 
 void
-LIRGeneratorMIPS::defineUntypedPhi(MPhi* phi, size_t lirIndex)
-{
-    LPhi* type = current->getPhi(lirIndex + VREG_TYPE_OFFSET);
-    LPhi* payload = current->getPhi(lirIndex + VREG_DATA_OFFSET);
-
-    uint32_t typeVreg = getVirtualRegister();
-    phi->setVirtualRegister(typeVreg);
-
-    uint32_t payloadVreg = getVirtualRegister();
-    MOZ_ASSERT(typeVreg + 1 == payloadVreg);
-
-    type->setDef(0, LDefinition(typeVreg, LDefinition::TYPE));
-    payload->setDef(0, LDefinition(payloadVreg, LDefinition::PAYLOAD));
-    annotate(type);
-    annotate(payload);
-}
-
-void
-LIRGeneratorMIPS::lowerUntypedPhiInput(MPhi* phi, uint32_t inputPosition,
-                                       LBlock* block, size_t lirIndex)
-{
-    MDefinition* operand = phi->getOperand(inputPosition);
-    LPhi* type = block->getPhi(lirIndex + VREG_TYPE_OFFSET);
-    LPhi* payload = block->getPhi(lirIndex + VREG_DATA_OFFSET);
-    type->setOperand(inputPosition, LUse(operand->virtualRegister() + VREG_TYPE_OFFSET,
-                                         LUse::ANY));
-    payload->setOperand(inputPosition, LUse(VirtualRegisterOfPayload(operand), LUse::ANY));
-}
-
-void
-LIRGeneratorMIPS::lowerForShift(LInstructionHelper<1, 2, 0>* ins, MDefinition* mir,
-                                MDefinition* lhs, MDefinition* rhs)
+LIRGeneratorMIPSShared::lowerForShift(LInstructionHelper<1, 2, 0>* ins, MDefinition* mir,
+                                      MDefinition* lhs, MDefinition* rhs)
 {
     ins->setOperand(0, useRegister(lhs));
     ins->setOperand(1, useRegisterOrConstant(rhs));
     define(ins, mir);
 }
 
 void
-LIRGeneratorMIPS::lowerDivI(MDiv* div)
+LIRGeneratorMIPSShared::lowerDivI(MDiv* div)
 {
     if (div->isUnsigned()) {
         lowerUDiv(div);
         return;
     }
 
     // Division instructions are slow. Division by constant denominators can be
     // rewritten to use other instructions.
@@ -266,27 +124,27 @@ LIRGeneratorMIPS::lowerDivI(MDiv* div)
 
     LDivI* lir = new(alloc()) LDivI(useRegister(div->lhs()), useRegister(div->rhs()), temp());
     if (div->fallible())
         assignSnapshot(lir, Bailout_DoubleOutput);
     define(lir, div);
 }
 
 void
-LIRGeneratorMIPS::lowerMulI(MMul* mul, MDefinition* lhs, MDefinition* rhs)
+LIRGeneratorMIPSShared::lowerMulI(MMul* mul, MDefinition* lhs, MDefinition* rhs)
 {
     LMulI* lir = new(alloc()) LMulI;
     if (mul->fallible())
         assignSnapshot(lir, Bailout_DoubleOutput);
 
     lowerForALU(lir, mul, lhs, rhs);
 }
 
 void
-LIRGeneratorMIPS::lowerModI(MMod* mod)
+LIRGeneratorMIPSShared::lowerModI(MMod* mod)
 {
     if (mod->isUnsigned()) {
         lowerUMod(mod);
         return;
     }
 
     if (mod->rhs()->isConstant()) {
         int32_t rhs = mod->rhs()->toConstant()->value().toInt32();
@@ -312,135 +170,135 @@ LIRGeneratorMIPS::lowerModI(MMod* mod)
                            temp(LDefinition::GENERAL));
 
     if (mod->fallible())
         assignSnapshot(lir, Bailout_DoubleOutput);
     define(lir, mod);
 }
 
 void
-LIRGeneratorMIPS::visitPowHalf(MPowHalf* ins)
+LIRGeneratorMIPSShared::visitPowHalf(MPowHalf* ins)
 {
     MDefinition* input = ins->input();
     MOZ_ASSERT(input->type() == MIRType_Double);
     LPowHalfD* lir = new(alloc()) LPowHalfD(useRegisterAtStart(input));
     defineReuseInput(lir, ins, 0);
 }
 
 LTableSwitch*
-LIRGeneratorMIPS::newLTableSwitch(const LAllocation& in, const LDefinition& inputCopy,
-                                  MTableSwitch* tableswitch)
+LIRGeneratorMIPSShared::newLTableSwitch(const LAllocation& in, const LDefinition& inputCopy,
+                                        MTableSwitch* tableswitch)
 {
     return new(alloc()) LTableSwitch(in, inputCopy, temp(), tableswitch);
 }
 
 LTableSwitchV*
-LIRGeneratorMIPS::newLTableSwitchV(MTableSwitch* tableswitch)
+LIRGeneratorMIPSShared::newLTableSwitchV(MTableSwitch* tableswitch)
 {
     return new(alloc()) LTableSwitchV(temp(), tempDouble(), temp(), tableswitch);
 }
 
 void
-LIRGeneratorMIPS::visitGuardShape(MGuardShape* ins)
+LIRGeneratorMIPSShared::visitGuardShape(MGuardShape* ins)
 {
     MOZ_ASSERT(ins->obj()->type() == MIRType_Object);
 
     LDefinition tempObj = temp(LDefinition::OBJECT);
     LGuardShape* guard = new(alloc()) LGuardShape(useRegister(ins->obj()), tempObj);
     assignSnapshot(guard, ins->bailoutKind());
     add(guard, ins);
     redefine(ins, ins->obj());
 }
 
 void
-LIRGeneratorMIPS::visitGuardObjectGroup(MGuardObjectGroup* ins)
+LIRGeneratorMIPSShared::visitGuardObjectGroup(MGuardObjectGroup* ins)
 {
     MOZ_ASSERT(ins->obj()->type() == MIRType_Object);
 
     LDefinition tempObj = temp(LDefinition::OBJECT);
     LGuardObjectGroup* guard = new(alloc()) LGuardObjectGroup(useRegister(ins->obj()), tempObj);
     assignSnapshot(guard, ins->bailoutKind());
     add(guard, ins);
     redefine(ins, ins->obj());
 }
 
 void
-LIRGeneratorMIPS::lowerUrshD(MUrsh* mir)
+LIRGeneratorMIPSShared::lowerUrshD(MUrsh* mir)
 {
     MDefinition* lhs = mir->lhs();
     MDefinition* rhs = mir->rhs();
 
     MOZ_ASSERT(lhs->type() == MIRType_Int32);
     MOZ_ASSERT(rhs->type() == MIRType_Int32);
 
     LUrshD* lir = new(alloc()) LUrshD(useRegister(lhs), useRegisterOrConstant(rhs), temp());
     define(lir, mir);
 }
 
 void
-LIRGeneratorMIPS::visitAsmJSNeg(MAsmJSNeg* ins)
+LIRGeneratorMIPSShared::visitAsmJSNeg(MAsmJSNeg* ins)
 {
     if (ins->type() == MIRType_Int32) {
         define(new(alloc()) LNegI(useRegisterAtStart(ins->input())), ins);
     } else if (ins->type() == MIRType_Float32) {
         define(new(alloc()) LNegF(useRegisterAtStart(ins->input())), ins);
     } else {
         MOZ_ASSERT(ins->type() == MIRType_Double);
         define(new(alloc()) LNegD(useRegisterAtStart(ins->input())), ins);
     }
 }
 
 void
-LIRGeneratorMIPS::lowerUDiv(MDiv* div)
+LIRGeneratorMIPSShared::lowerUDiv(MDiv* div)
 {
     MDefinition* lhs = div->getOperand(0);
     MDefinition* rhs = div->getOperand(1);
 
     LUDivOrMod* lir = new(alloc()) LUDivOrMod;
     lir->setOperand(0, useRegister(lhs));
     lir->setOperand(1, useRegister(rhs));
     if (div->fallible())
         assignSnapshot(lir, Bailout_DoubleOutput);
 
     define(lir, div);
 }
 
 void
-LIRGeneratorMIPS::lowerUMod(MMod* mod)
+LIRGeneratorMIPSShared::lowerUMod(MMod* mod)
 {
     MDefinition* lhs = mod->getOperand(0);
     MDefinition* rhs = mod->getOperand(1);
 
     LUDivOrMod* lir = new(alloc()) LUDivOrMod;
     lir->setOperand(0, useRegister(lhs));
     lir->setOperand(1, useRegister(rhs));
     if (mod->fallible())
         assignSnapshot(lir, Bailout_DoubleOutput);
 
     define(lir, mod);
 }
 
 void
-LIRGeneratorMIPS::visitAsmJSUnsignedToDouble(MAsmJSUnsignedToDouble* ins)
+LIRGeneratorMIPSShared::visitAsmJSUnsignedToDouble(MAsmJSUnsignedToDouble* ins)
 {
     MOZ_ASSERT(ins->input()->type() == MIRType_Int32);
     LAsmJSUInt32ToDouble* lir = new(alloc()) LAsmJSUInt32ToDouble(useRegisterAtStart(ins->input()));
     define(lir, ins);
 }
 
 void
-LIRGeneratorMIPS::visitAsmJSUnsignedToFloat32(MAsmJSUnsignedToFloat32* ins)
+LIRGeneratorMIPSShared::visitAsmJSUnsignedToFloat32(MAsmJSUnsignedToFloat32* ins)
 {
     MOZ_ASSERT(ins->input()->type() == MIRType_Int32);
     LAsmJSUInt32ToFloat32* lir = new(alloc()) LAsmJSUInt32ToFloat32(useRegisterAtStart(ins->input()));
     define(lir, ins);
 }
 
 void
-LIRGeneratorMIPS::visitAsmJSLoadHeap(MAsmJSLoadHeap* ins)
+LIRGeneratorMIPSShared::visitAsmJSLoadHeap(MAsmJSLoadHeap* ins)
 {
     MDefinition* ptr = ins->ptr();
     MOZ_ASSERT(ptr->type() == MIRType_Int32);
     LAllocation ptrAlloc;
 
     // For MIPS it is best to keep the 'ptr' in a register if a bounds check
     // is needed.
     if (ptr->isConstantValue() && !ins->needsBoundsCheck()) {
@@ -449,132 +307,114 @@ LIRGeneratorMIPS::visitAsmJSLoadHeap(MAs
         ptrAlloc = LAllocation(ptr->constantVp());
     } else
         ptrAlloc = useRegisterAtStart(ptr);
 
     define(new(alloc()) LAsmJSLoadHeap(ptrAlloc), ins);
 }
 
 void
-LIRGeneratorMIPS::visitAsmJSStoreHeap(MAsmJSStoreHeap* ins)
+LIRGeneratorMIPSShared::visitAsmJSStoreHeap(MAsmJSStoreHeap* ins)
 {
     MDefinition* ptr = ins->ptr();
     MOZ_ASSERT(ptr->type() == MIRType_Int32);
     LAllocation ptrAlloc;
 
     if (ptr->isConstantValue() && !ins->needsBoundsCheck()) {
         MOZ_ASSERT(ptr->constantValue().toInt32() >= 0);
         ptrAlloc = LAllocation(ptr->constantVp());
     } else
         ptrAlloc = useRegisterAtStart(ptr);
 
     add(new(alloc()) LAsmJSStoreHeap(ptrAlloc, useRegisterAtStart(ins->value())), ins);
 }
 
 void
-LIRGeneratorMIPS::visitAsmJSLoadFuncPtr(MAsmJSLoadFuncPtr* ins)
+LIRGeneratorMIPSShared::visitAsmJSLoadFuncPtr(MAsmJSLoadFuncPtr* ins)
 {
     define(new(alloc()) LAsmJSLoadFuncPtr(useRegister(ins->index())), ins);
 }
 
 void
-LIRGeneratorMIPS::lowerTruncateDToInt32(MTruncateToInt32* ins)
-{
-    MDefinition* opd = ins->input();
-    MOZ_ASSERT(opd->type() == MIRType_Double);
-
-    define(new(alloc()) LTruncateDToInt32(useRegister(opd), LDefinition::BogusTemp()), ins);
-}
-
-void
-LIRGeneratorMIPS::lowerTruncateFToInt32(MTruncateToInt32* ins)
-{
-    MDefinition* opd = ins->input();
-    MOZ_ASSERT(opd->type() == MIRType_Float32);
-
-    define(new(alloc()) LTruncateFToInt32(useRegister(opd), LDefinition::BogusTemp()), ins);
-}
-
-void
-LIRGeneratorMIPS::visitSubstr(MSubstr* ins)
+LIRGeneratorMIPSShared::visitSubstr(MSubstr* ins)
 {
     LSubstr* lir = new (alloc()) LSubstr(useRegister(ins->string()),
                                          useRegister(ins->begin()),
                                          useRegister(ins->length()),
                                          temp(),
                                          temp(),
                                          tempByteOpRegister());
     define(lir, ins);
     assignSafepoint(lir, ins);
 }
 
 void
-LIRGeneratorMIPS::visitStoreTypedArrayElementStatic(MStoreTypedArrayElementStatic* ins)
+LIRGeneratorMIPSShared::visitStoreTypedArrayElementStatic(MStoreTypedArrayElementStatic* ins)
 {
     MOZ_CRASH("NYI");
 }
 
 void
-LIRGeneratorMIPS::visitSimdBinaryArith(MSimdBinaryArith* ins)
+LIRGeneratorMIPSShared::visitSimdBinaryArith(MSimdBinaryArith* ins)
 {
     MOZ_CRASH("NYI");
 }
 
 void
-LIRGeneratorMIPS::visitSimdSelect(MSimdSelect* ins)
+LIRGeneratorMIPSShared::visitSimdSelect(MSimdSelect* ins)
 {
     MOZ_CRASH("NYI");
 }
 
 void
-LIRGeneratorMIPS::visitSimdSplatX4(MSimdSplatX4* ins)
+LIRGeneratorMIPSShared::visitSimdSplatX4(MSimdSplatX4* ins)
 {
     MOZ_CRASH("NYI");
 }
 
 void
-LIRGeneratorMIPS::visitSimdValueX4(MSimdValueX4* ins)
+LIRGeneratorMIPSShared::visitSimdValueX4(MSimdValueX4* ins)
 {
     MOZ_CRASH("NYI");
 }
 
 void
-LIRGeneratorMIPS::visitCompareExchangeTypedArrayElement(MCompareExchangeTypedArrayElement* ins)
+LIRGeneratorMIPSShared::visitCompareExchangeTypedArrayElement(MCompareExchangeTypedArrayElement* ins)
 {
     MOZ_CRASH("NYI");
 }
 
 void
-LIRGeneratorMIPS::visitAtomicExchangeTypedArrayElement(MAtomicExchangeTypedArrayElement* ins)
+LIRGeneratorMIPSShared::visitAtomicExchangeTypedArrayElement(MAtomicExchangeTypedArrayElement* ins)
 {
     MOZ_CRASH("NYI");
 }
 
 void
-LIRGeneratorMIPS::visitAsmJSCompareExchangeHeap(MAsmJSCompareExchangeHeap* ins)
+LIRGeneratorMIPSShared::visitAsmJSCompareExchangeHeap(MAsmJSCompareExchangeHeap* ins)
 {
     MOZ_CRASH("NYI");
 }
 
 void
-LIRGeneratorMIPS::visitAsmJSAtomicExchangeHeap(MAsmJSAtomicExchangeHeap* ins)
+LIRGeneratorMIPSShared::visitAsmJSAtomicExchangeHeap(MAsmJSAtomicExchangeHeap* ins)
 {
     MOZ_CRASH("NYI");
 }
 
 void
-LIRGeneratorMIPS::visitAsmJSAtomicBinopHeap(MAsmJSAtomicBinopHeap* ins)
+LIRGeneratorMIPSShared::visitAsmJSAtomicBinopHeap(MAsmJSAtomicBinopHeap* ins)
 {
     MOZ_CRASH("NYI");
 }
 
 void
-LIRGeneratorMIPS::visitAtomicTypedArrayElementBinop(MAtomicTypedArrayElementBinop* ins)
+LIRGeneratorMIPSShared::visitAtomicTypedArrayElementBinop(MAtomicTypedArrayElementBinop* ins)
 {
     MOZ_CRASH("NYI");
 }
 
 void
-LIRGeneratorMIPS::visitRandom(MRandom* ins)
+LIRGeneratorMIPSShared::visitRandom(MRandom* ins)
 {
     LRandom* lir = new(alloc()) LRandom(tempFixed(CallTempReg0), tempFixed(CallTempReg1));
     defineReturn(lir, ins);
 }
copy from js/src/jit/mips32/Lowering-mips32.h
copy to js/src/jit/mips-shared/Lowering-mips-shared.h
--- a/js/src/jit/mips32/Lowering-mips32.h
+++ b/js/src/jit/mips-shared/Lowering-mips-shared.h
@@ -1,49 +1,38 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  * vim: set ts=8 sts=4 et sw=4 tw=99:
  * 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 jit_mips32_Lowering_mips32_h
-#define jit_mips32_Lowering_mips32_h
+#ifndef jit_mips_shared_Lowering_mips_shared_h
+#define jit_mips_shared_Lowering_mips_shared_h
 
 #include "jit/shared/Lowering-shared.h"
 
 namespace js {
 namespace jit {
 
-class LIRGeneratorMIPS : public LIRGeneratorShared
+class LIRGeneratorMIPSShared : public LIRGeneratorShared
 {
   protected:
-    LIRGeneratorMIPS(MIRGenerator* gen, MIRGraph& graph, LIRGraph& lirGraph)
+    LIRGeneratorMIPSShared(MIRGenerator* gen, MIRGraph& graph, LIRGraph& lirGraph)
       : LIRGeneratorShared(gen, graph, lirGraph)
     { }
 
   protected:
-    // Adds a box input to an instruction, setting operand |n| to the type and
-    // |n+1| to the payload.
-    void useBoxFixed(LInstruction* lir, size_t n, MDefinition* mir, Register reg1, Register reg2,
-                     bool useAtStart = false);
-
     // x86 has constraints on what registers can be formatted for 1-byte
     // stores and loads; on MIPS all registers are okay.
     LAllocation useByteOpRegister(MDefinition* mir);
     LAllocation useByteOpRegisterOrNonDoubleConstant(MDefinition* mir);
     LDefinition tempByteOpRegister();
 
-    inline LDefinition tempToUnbox() {
-        return LDefinition::BogusTemp();
-    }
-
     bool needTempForPostBarrier() { return false; }
 
-    void lowerUntypedPhiInput(MPhi* phi, uint32_t inputPosition, LBlock* block, size_t lirIndex);
-    void defineUntypedPhi(MPhi* phi, size_t lirIndex);
     void lowerForShift(LInstructionHelper<1, 2, 0>* ins, MDefinition* mir, MDefinition* lhs,
                        MDefinition* rhs);
     void lowerUrshD(MUrsh* mir);
 
     void lowerForALU(LInstructionHelper<1, 1, 0>* ins, MDefinition* mir,
                      MDefinition* input);
     void lowerForALU(LInstructionHelper<1, 2, 0>* ins, MDefinition* mir,
                      MDefinition* lhs, MDefinition* rhs);
@@ -62,34 +51,29 @@ class LIRGeneratorMIPS : public LIRGener
     void lowerForCompFx4(LSimdBinaryCompFx4* ins, MSimdBinaryComp* mir,
                          MDefinition* lhs, MDefinition* rhs)
     {
         return lowerForFPU(ins, mir, lhs, rhs);
     }
 
     void lowerForBitAndAndBranch(LBitAndAndBranch* baab, MInstruction* mir,
                                  MDefinition* lhs, MDefinition* rhs);
-    void lowerTruncateDToInt32(MTruncateToInt32* ins);
-    void lowerTruncateFToInt32(MTruncateToInt32* ins);
     void lowerDivI(MDiv* div);
     void lowerModI(MMod* mod);
     void lowerMulI(MMul* mul, MDefinition* lhs, MDefinition* rhs);
     void lowerUDiv(MDiv* div);
     void lowerUMod(MMod* mod);
     void visitPowHalf(MPowHalf* ins);
     void visitAsmJSNeg(MAsmJSNeg* ins);
 
     LTableSwitch* newLTableSwitch(const LAllocation& in, const LDefinition& inputCopy,
                                   MTableSwitch* ins);
     LTableSwitchV* newLTableSwitchV(MTableSwitch* ins);
 
   public:
-    void visitBox(MBox* box);
-    void visitUnbox(MUnbox* unbox);
-    void visitReturn(MReturn* ret);
     void lowerPhi(MPhi* phi);
     void visitGuardShape(MGuardShape* ins);
     void visitGuardObjectGroup(MGuardObjectGroup* ins);
     void visitAsmJSUnsignedToDouble(MAsmJSUnsignedToDouble* ins);
     void visitAsmJSUnsignedToFloat32(MAsmJSUnsignedToFloat32* ins);
     void visitAsmJSLoadHeap(MAsmJSLoadHeap* ins);
     void visitAsmJSStoreHeap(MAsmJSStoreHeap* ins);
     void visitAsmJSCompareExchangeHeap(MAsmJSCompareExchangeHeap* ins);
@@ -103,14 +87,12 @@ class LIRGeneratorMIPS : public LIRGener
     void visitSimdValueX4(MSimdValueX4* ins);
     void visitCompareExchangeTypedArrayElement(MCompareExchangeTypedArrayElement* ins);
     void visitAtomicExchangeTypedArrayElement(MAtomicExchangeTypedArrayElement* ins);
     void visitAtomicTypedArrayElementBinop(MAtomicTypedArrayElementBinop* ins);
     void visitSubstr(MSubstr* ins);
     void visitRandom(MRandom* ins);
 };
 
-typedef LIRGeneratorMIPS LIRGeneratorSpecific;
-
 } // namespace jit
 } // namespace js
 
-#endif /* jit_mips32_Lowering_mips32_h */
+#endif /* jit_mips_shared_Lowering_mips_shared_h */
--- a/js/src/jit/mips32/Lowering-mips32.cpp
+++ b/js/src/jit/mips32/Lowering-mips32.cpp
@@ -1,58 +1,37 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  * vim: set ts=8 sts=4 et sw=4 tw=99:
  * 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 "mozilla/MathAlgorithms.h"
-
+#include "jit/mips32/Lowering-mips32.h"
 
-#include "jit/Lowering.h"
 #include "jit/mips32/Assembler-mips32.h"
+
 #include "jit/MIR.h"
 
 #include "jit/shared/Lowering-shared-inl.h"
 
 using namespace js;
 using namespace js::jit;
 
-using mozilla::FloorLog2;
-
 void
 LIRGeneratorMIPS::useBoxFixed(LInstruction* lir, size_t n, MDefinition* mir, Register reg1,
                               Register reg2, bool useAtStart)
 {
     MOZ_ASSERT(mir->type() == MIRType_Value);
     MOZ_ASSERT(reg1 != reg2);
 
     ensureDefined(mir);
     lir->setOperand(n, LUse(reg1, mir->virtualRegister(), useAtStart));
     lir->setOperand(n + 1, LUse(reg2, VirtualRegisterOfPayload(mir), useAtStart));
 }
 
-LAllocation
-LIRGeneratorMIPS::useByteOpRegister(MDefinition* mir)
-{
-    return useRegister(mir);
-}
-
-LAllocation
-LIRGeneratorMIPS::useByteOpRegisterOrNonDoubleConstant(MDefinition* mir)
-{
-    return useRegisterOrNonDoubleConstant(mir);
-}
-
-LDefinition
-LIRGeneratorMIPS::tempByteOpRegister()
-{
-    return temp();
-}
-
 void
 LIRGeneratorMIPS::visitBox(MBox* box)
 {
     MDefinition* inner = box->getOperand(0);
 
     // If the box wrapped a double, it needs a new register.
     if (IsFloatingPointType(inner->type())) {
         defineBox(new(alloc()) LBoxFloatingPoint(useRegisterAtStart(inner),
@@ -142,67 +121,16 @@ LIRGeneratorMIPS::visitReturn(MReturn* r
 
     LReturn* ins = new(alloc()) LReturn;
     ins->setOperand(0, LUse(JSReturnReg_Type));
     ins->setOperand(1, LUse(JSReturnReg_Data));
     fillBoxUses(ins, 0, opd);
     add(ins);
 }
 
-// x = !y
-void
-LIRGeneratorMIPS::lowerForALU(LInstructionHelper<1, 1, 0>* ins,
-                              MDefinition* mir, MDefinition* input)
-{
-    ins->setOperand(0, useRegister(input));
-    define(ins, mir, LDefinition(LDefinition::TypeFrom(mir->type()), LDefinition::REGISTER));
-}
-
-// z = x+y
-void
-LIRGeneratorMIPS::lowerForALU(LInstructionHelper<1, 2, 0>* ins, MDefinition* mir,
-                              MDefinition* lhs, MDefinition* rhs)
-{
-    ins->setOperand(0, useRegister(lhs));
-    ins->setOperand(1, useRegisterOrConstant(rhs));
-    define(ins, mir, LDefinition(LDefinition::TypeFrom(mir->type()), LDefinition::REGISTER));
-}
-
-void
-LIRGeneratorMIPS::lowerForFPU(LInstructionHelper<1, 1, 0>* ins, MDefinition* mir,
-                              MDefinition* input)
-{
-    ins->setOperand(0, useRegister(input));
-    define(ins, mir, LDefinition(LDefinition::TypeFrom(mir->type()), LDefinition::REGISTER));
-}
-
-template<size_t Temps>
-void
-LIRGeneratorMIPS::lowerForFPU(LInstructionHelper<1, 2, Temps>* ins, MDefinition* mir,
-                              MDefinition* lhs, MDefinition* rhs)
-{
-    ins->setOperand(0, useRegister(lhs));
-    ins->setOperand(1, useRegister(rhs));
-    define(ins, mir, LDefinition(LDefinition::TypeFrom(mir->type()), LDefinition::REGISTER));
-}
-
-template void LIRGeneratorMIPS::lowerForFPU(LInstructionHelper<1, 2, 0>* ins, MDefinition* mir,
-                                            MDefinition* lhs, MDefinition* rhs);
-template void LIRGeneratorMIPS::lowerForFPU(LInstructionHelper<1, 2, 1>* ins, MDefinition* mir,
-                                            MDefinition* lhs, MDefinition* rhs);
-
-void
-LIRGeneratorMIPS::lowerForBitAndAndBranch(LBitAndAndBranch* baab, MInstruction* mir,
-                                          MDefinition* lhs, MDefinition* rhs)
-{
-    baab->setOperand(0, useRegisterAtStart(lhs));
-    baab->setOperand(1, useRegisterOrConstantAtStart(rhs));
-    add(baab, mir);
-}
-
 void
 LIRGeneratorMIPS::defineUntypedPhi(MPhi* phi, size_t lirIndex)
 {
     LPhi* type = current->getPhi(lirIndex + VREG_TYPE_OFFSET);
     LPhi* payload = current->getPhi(lirIndex + VREG_DATA_OFFSET);
 
     uint32_t typeVreg = getVirtualRegister();
     phi->setVirtualRegister(typeVreg);
@@ -224,357 +152,24 @@ LIRGeneratorMIPS::lowerUntypedPhiInput(M
     LPhi* type = block->getPhi(lirIndex + VREG_TYPE_OFFSET);
     LPhi* payload = block->getPhi(lirIndex + VREG_DATA_OFFSET);
     type->setOperand(inputPosition, LUse(operand->virtualRegister() + VREG_TYPE_OFFSET,
                                          LUse::ANY));
     payload->setOperand(inputPosition, LUse(VirtualRegisterOfPayload(operand), LUse::ANY));
 }
 
 void
-LIRGeneratorMIPS::lowerForShift(LInstructionHelper<1, 2, 0>* ins, MDefinition* mir,
-                                MDefinition* lhs, MDefinition* rhs)
-{
-    ins->setOperand(0, useRegister(lhs));
-    ins->setOperand(1, useRegisterOrConstant(rhs));
-    define(ins, mir);
-}
-
-void
-LIRGeneratorMIPS::lowerDivI(MDiv* div)
-{
-    if (div->isUnsigned()) {
-        lowerUDiv(div);
-        return;
-    }
-
-    // Division instructions are slow. Division by constant denominators can be
-    // rewritten to use other instructions.
-    if (div->rhs()->isConstant()) {
-        int32_t rhs = div->rhs()->toConstant()->value().toInt32();
-        // Check for division by a positive power of two, which is an easy and
-        // important case to optimize. Note that other optimizations are also
-        // possible; division by negative powers of two can be optimized in a
-        // similar manner as positive powers of two, and division by other
-        // constants can be optimized by a reciprocal multiplication technique.
-        int32_t shift = FloorLog2(rhs);
-        if (rhs > 0 && 1 << shift == rhs) {
-            LDivPowTwoI* lir = new(alloc()) LDivPowTwoI(useRegister(div->lhs()), shift, temp());
-            if (div->fallible())
-                assignSnapshot(lir, Bailout_DoubleOutput);
-            define(lir, div);
-            return;
-        }
-    }
-
-    LDivI* lir = new(alloc()) LDivI(useRegister(div->lhs()), useRegister(div->rhs()), temp());
-    if (div->fallible())
-        assignSnapshot(lir, Bailout_DoubleOutput);
-    define(lir, div);
-}
-
-void
-LIRGeneratorMIPS::lowerMulI(MMul* mul, MDefinition* lhs, MDefinition* rhs)
-{
-    LMulI* lir = new(alloc()) LMulI;
-    if (mul->fallible())
-        assignSnapshot(lir, Bailout_DoubleOutput);
-
-    lowerForALU(lir, mul, lhs, rhs);
-}
-
-void
-LIRGeneratorMIPS::lowerModI(MMod* mod)
-{
-    if (mod->isUnsigned()) {
-        lowerUMod(mod);
-        return;
-    }
-
-    if (mod->rhs()->isConstant()) {
-        int32_t rhs = mod->rhs()->toConstant()->value().toInt32();
-        int32_t shift = FloorLog2(rhs);
-        if (rhs > 0 && 1 << shift == rhs) {
-            LModPowTwoI* lir = new(alloc()) LModPowTwoI(useRegister(mod->lhs()), shift);
-            if (mod->fallible())
-                assignSnapshot(lir, Bailout_DoubleOutput);
-            define(lir, mod);
-            return;
-        } else if (shift < 31 && (1 << (shift + 1)) - 1 == rhs) {
-            LModMaskI* lir = new(alloc()) LModMaskI(useRegister(mod->lhs()),
-                                                    temp(LDefinition::GENERAL),
-                                                    temp(LDefinition::GENERAL),
-                                                    shift + 1);
-            if (mod->fallible())
-                assignSnapshot(lir, Bailout_DoubleOutput);
-            define(lir, mod);
-            return;
-        }
-    }
-    LModI* lir = new(alloc()) LModI(useRegister(mod->lhs()), useRegister(mod->rhs()),
-                           temp(LDefinition::GENERAL));
-
-    if (mod->fallible())
-        assignSnapshot(lir, Bailout_DoubleOutput);
-    define(lir, mod);
-}
-
-void
-LIRGeneratorMIPS::visitPowHalf(MPowHalf* ins)
-{
-    MDefinition* input = ins->input();
-    MOZ_ASSERT(input->type() == MIRType_Double);
-    LPowHalfD* lir = new(alloc()) LPowHalfD(useRegisterAtStart(input));
-    defineReuseInput(lir, ins, 0);
-}
-
-LTableSwitch*
-LIRGeneratorMIPS::newLTableSwitch(const LAllocation& in, const LDefinition& inputCopy,
-                                  MTableSwitch* tableswitch)
-{
-    return new(alloc()) LTableSwitch(in, inputCopy, temp(), tableswitch);
-}
-
-LTableSwitchV*
-LIRGeneratorMIPS::newLTableSwitchV(MTableSwitch* tableswitch)
-{
-    return new(alloc()) LTableSwitchV(temp(), tempDouble(), temp(), tableswitch);
-}
-
-void
-LIRGeneratorMIPS::visitGuardShape(MGuardShape* ins)
-{
-    MOZ_ASSERT(ins->obj()->type() == MIRType_Object);
-
-    LDefinition tempObj = temp(LDefinition::OBJECT);
-    LGuardShape* guard = new(alloc()) LGuardShape(useRegister(ins->obj()), tempObj);
-    assignSnapshot(guard, ins->bailoutKind());
-    add(guard, ins);
-    redefine(ins, ins->obj());
-}
-
-void
-LIRGeneratorMIPS::visitGuardObjectGroup(MGuardObjectGroup* ins)
-{
-    MOZ_ASSERT(ins->obj()->type() == MIRType_Object);
-
-    LDefinition tempObj = temp(LDefinition::OBJECT);
-    LGuardObjectGroup* guard = new(alloc()) LGuardObjectGroup(useRegister(ins->obj()), tempObj);
-    assignSnapshot(guard, ins->bailoutKind());
-    add(guard, ins);
-    redefine(ins, ins->obj());
-}
-
-void
-LIRGeneratorMIPS::lowerUrshD(MUrsh* mir)
-{
-    MDefinition* lhs = mir->lhs();
-    MDefinition* rhs = mir->rhs();
-
-    MOZ_ASSERT(lhs->type() == MIRType_Int32);
-    MOZ_ASSERT(rhs->type() == MIRType_Int32);
-
-    LUrshD* lir = new(alloc()) LUrshD(useRegister(lhs), useRegisterOrConstant(rhs), temp());
-    define(lir, mir);
-}
-
-void
-LIRGeneratorMIPS::visitAsmJSNeg(MAsmJSNeg* ins)
-{
-    if (ins->type() == MIRType_Int32) {
-        define(new(alloc()) LNegI(useRegisterAtStart(ins->input())), ins);
-    } else if (ins->type() == MIRType_Float32) {
-        define(new(alloc()) LNegF(useRegisterAtStart(ins->input())), ins);
-    } else {
-        MOZ_ASSERT(ins->type() == MIRType_Double);
-        define(new(alloc()) LNegD(useRegisterAtStart(ins->input())), ins);
-    }
-}
-
-void
-LIRGeneratorMIPS::lowerUDiv(MDiv* div)
-{
-    MDefinition* lhs = div->getOperand(0);
-    MDefinition* rhs = div->getOperand(1);
-
-    LUDivOrMod* lir = new(alloc()) LUDivOrMod;
-    lir->setOperand(0, useRegister(lhs));
-    lir->setOperand(1, useRegister(rhs));
-    if (div->fallible())
-        assignSnapshot(lir, Bailout_DoubleOutput);
-
-    define(lir, div);
-}
-
-void
-LIRGeneratorMIPS::lowerUMod(MMod* mod)
-{
-    MDefinition* lhs = mod->getOperand(0);
-    MDefinition* rhs = mod->getOperand(1);
-
-    LUDivOrMod* lir = new(alloc()) LUDivOrMod;
-    lir->setOperand(0, useRegister(lhs));
-    lir->setOperand(1, useRegister(rhs));
-    if (mod->fallible())
-        assignSnapshot(lir, Bailout_DoubleOutput);
-
-    define(lir, mod);
-}
-
-void
-LIRGeneratorMIPS::visitAsmJSUnsignedToDouble(MAsmJSUnsignedToDouble* ins)
-{
-    MOZ_ASSERT(ins->input()->type() == MIRType_Int32);
-    LAsmJSUInt32ToDouble* lir = new(alloc()) LAsmJSUInt32ToDouble(useRegisterAtStart(ins->input()));
-    define(lir, ins);
-}
-
-void
-LIRGeneratorMIPS::visitAsmJSUnsignedToFloat32(MAsmJSUnsignedToFloat32* ins)
-{
-    MOZ_ASSERT(ins->input()->type() == MIRType_Int32);
-    LAsmJSUInt32ToFloat32* lir = new(alloc()) LAsmJSUInt32ToFloat32(useRegisterAtStart(ins->input()));
-    define(lir, ins);
-}
-
-void
-LIRGeneratorMIPS::visitAsmJSLoadHeap(MAsmJSLoadHeap* ins)
-{
-    MDefinition* ptr = ins->ptr();
-    MOZ_ASSERT(ptr->type() == MIRType_Int32);
-    LAllocation ptrAlloc;
-
-    // For MIPS it is best to keep the 'ptr' in a register if a bounds check
-    // is needed.
-    if (ptr->isConstantValue() && !ins->needsBoundsCheck()) {
-        // A bounds check is only skipped for a positive index.
-        MOZ_ASSERT(ptr->constantValue().toInt32() >= 0);
-        ptrAlloc = LAllocation(ptr->constantVp());
-    } else
-        ptrAlloc = useRegisterAtStart(ptr);
-
-    define(new(alloc()) LAsmJSLoadHeap(ptrAlloc), ins);
-}
-
-void
-LIRGeneratorMIPS::visitAsmJSStoreHeap(MAsmJSStoreHeap* ins)
-{
-    MDefinition* ptr = ins->ptr();
-    MOZ_ASSERT(ptr->type() == MIRType_Int32);
-    LAllocation ptrAlloc;
-
-    if (ptr->isConstantValue() && !ins->needsBoundsCheck()) {
-        MOZ_ASSERT(ptr->constantValue().toInt32() >= 0);
-        ptrAlloc = LAllocation(ptr->constantVp());
-    } else
-        ptrAlloc = useRegisterAtStart(ptr);
-
-    add(new(alloc()) LAsmJSStoreHeap(ptrAlloc, useRegisterAtStart(ins->value())), ins);
-}
-
-void
-LIRGeneratorMIPS::visitAsmJSLoadFuncPtr(MAsmJSLoadFuncPtr* ins)
-{
-    define(new(alloc()) LAsmJSLoadFuncPtr(useRegister(ins->index())), ins);
-}
-
-void
 LIRGeneratorMIPS::lowerTruncateDToInt32(MTruncateToInt32* ins)
 {
     MDefinition* opd = ins->input();
     MOZ_ASSERT(opd->type() == MIRType_Double);
 
     define(new(alloc()) LTruncateDToInt32(useRegister(opd), LDefinition::BogusTemp()), ins);
 }
 
 void
 LIRGeneratorMIPS::lowerTruncateFToInt32(MTruncateToInt32* ins)
 {
     MDefinition* opd = ins->input();
     MOZ_ASSERT(opd->type() == MIRType_Float32);
 
     define(new(alloc()) LTruncateFToInt32(useRegister(opd), LDefinition::BogusTemp()), ins);
 }
-
-void
-LIRGeneratorMIPS::visitSubstr(MSubstr* ins)
-{
-    LSubstr* lir = new (alloc()) LSubstr(useRegister(ins->string()),
-                                         useRegister(ins->begin()),
-                                         useRegister(ins->length()),
-                                         temp(),
-                                         temp(),
-                                         tempByteOpRegister());
-    define(lir, ins);
-    assignSafepoint(lir, ins);
-}
-
-void
-LIRGeneratorMIPS::visitStoreTypedArrayElementStatic(MStoreTypedArrayElementStatic* ins)
-{
-    MOZ_CRASH("NYI");
-}
-
-void
-LIRGeneratorMIPS::visitSimdBinaryArith(MSimdBinaryArith* ins)
-{
-    MOZ_CRASH("NYI");
-}
-
-void
-LIRGeneratorMIPS::visitSimdSelect(MSimdSelect* ins)
-{
-    MOZ_CRASH("NYI");
-}
-
-void
-LIRGeneratorMIPS::visitSimdSplatX4(MSimdSplatX4* ins)
-{
-    MOZ_CRASH("NYI");
-}
-
-void
-LIRGeneratorMIPS::visitSimdValueX4(MSimdValueX4* ins)
-{
-    MOZ_CRASH("NYI");
-}
-
-void
-LIRGeneratorMIPS::visitCompareExchangeTypedArrayElement(MCompareExchangeTypedArrayElement* ins)
-{
-    MOZ_CRASH("NYI");
-}
-
-void
-LIRGeneratorMIPS::visitAtomicExchangeTypedArrayElement(MAtomicExchangeTypedArrayElement* ins)
-{
-    MOZ_CRASH("NYI");
-}
-
-void
-LIRGeneratorMIPS::visitAsmJSCompareExchangeHeap(MAsmJSCompareExchangeHeap* ins)
-{
-    MOZ_CRASH("NYI");
-}
-
-void
-LIRGeneratorMIPS::visitAsmJSAtomicExchangeHeap(MAsmJSAtomicExchangeHeap* ins)
-{
-    MOZ_CRASH("NYI");
-}
-
-void
-LIRGeneratorMIPS::visitAsmJSAtomicBinopHeap(MAsmJSAtomicBinopHeap* ins)
-{
-    MOZ_CRASH("NYI");
-}
-
-void
-LIRGeneratorMIPS::visitAtomicTypedArrayElementBinop(MAtomicTypedArrayElementBinop* ins)
-{
-    MOZ_CRASH("NYI");
-}
-
-void
-LIRGeneratorMIPS::visitRandom(MRandom* ins)
-{
-    LRandom* lir = new(alloc()) LRandom(tempFixed(CallTempReg0), tempFixed(CallTempReg1));
-    defineReturn(lir, ins);
-}
--- a/js/src/jit/mips32/Lowering-mips32.h
+++ b/js/src/jit/mips32/Lowering-mips32.h
@@ -2,115 +2,48 @@
  * vim: set ts=8 sts=4 et sw=4 tw=99:
  * 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 jit_mips32_Lowering_mips32_h
 #define jit_mips32_Lowering_mips32_h
 
-#include "jit/shared/Lowering-shared.h"
+#include "jit/mips-shared/Lowering-mips-shared.h"
 
 namespace js {
 namespace jit {
 
-class LIRGeneratorMIPS : public LIRGeneratorShared
+class LIRGeneratorMIPS : public LIRGeneratorMIPSShared
 {
   protected:
     LIRGeneratorMIPS(MIRGenerator* gen, MIRGraph& graph, LIRGraph& lirGraph)
-      : LIRGeneratorShared(gen, graph, lirGraph)
+      : LIRGeneratorMIPSShared(gen, graph, lirGraph)
     { }
 
   protected:
     // Adds a box input to an instruction, setting operand |n| to the type and
     // |n+1| to the payload.
     void useBoxFixed(LInstruction* lir, size_t n, MDefinition* mir, Register reg1, Register reg2,
                      bool useAtStart = false);
 
-    // x86 has constraints on what registers can be formatted for 1-byte
-    // stores and loads; on MIPS all registers are okay.
-    LAllocation useByteOpRegister(MDefinition* mir);
-    LAllocation useByteOpRegisterOrNonDoubleConstant(MDefinition* mir);
-    LDefinition tempByteOpRegister();
-
     inline LDefinition tempToUnbox() {
         return LDefinition::BogusTemp();
     }
 
-    bool needTempForPostBarrier() { return false; }
-
     void lowerUntypedPhiInput(MPhi* phi, uint32_t inputPosition, LBlock* block, size_t lirIndex);
     void defineUntypedPhi(MPhi* phi, size_t lirIndex);
-    void lowerForShift(LInstructionHelper<1, 2, 0>* ins, MDefinition* mir, MDefinition* lhs,
-                       MDefinition* rhs);
-    void lowerUrshD(MUrsh* mir);
 
-    void lowerForALU(LInstructionHelper<1, 1, 0>* ins, MDefinition* mir,
-                     MDefinition* input);
-    void lowerForALU(LInstructionHelper<1, 2, 0>* ins, MDefinition* mir,
-                     MDefinition* lhs, MDefinition* rhs);
-
-    void lowerForFPU(LInstructionHelper<1, 1, 0>* ins, MDefinition* mir,
-                     MDefinition* src);
-    template<size_t Temps>
-    void lowerForFPU(LInstructionHelper<1, 2, Temps>* ins, MDefinition* mir,
-                     MDefinition* lhs, MDefinition* rhs);
-
-    void lowerForCompIx4(LSimdBinaryCompIx4* ins, MSimdBinaryComp* mir,
-                         MDefinition* lhs, MDefinition* rhs)
-    {
-        return lowerForFPU(ins, mir, lhs, rhs);
-    }
-    void lowerForCompFx4(LSimdBinaryCompFx4* ins, MSimdBinaryComp* mir,
-                         MDefinition* lhs, MDefinition* rhs)
-    {
-        return lowerForFPU(ins, mir, lhs, rhs);
-    }
-
-    void lowerForBitAndAndBranch(LBitAndAndBranch* baab, MInstruction* mir,
-                                 MDefinition* lhs, MDefinition* rhs);
     void lowerTruncateDToInt32(MTruncateToInt32* ins);
     void lowerTruncateFToInt32(MTruncateToInt32* ins);
-    void lowerDivI(MDiv* div);
-    void lowerModI(MMod* mod);
-    void lowerMulI(MMul* mul, MDefinition* lhs, MDefinition* rhs);
-    void lowerUDiv(MDiv* div);
-    void lowerUMod(MMod* mod);
-    void visitPowHalf(MPowHalf* ins);
-    void visitAsmJSNeg(MAsmJSNeg* ins);
-
-    LTableSwitch* newLTableSwitch(const LAllocation& in, const LDefinition& inputCopy,
-                                  MTableSwitch* ins);
-    LTableSwitchV* newLTableSwitchV(MTableSwitch* ins);
 
   public:
     void visitBox(MBox* box);
     void visitUnbox(MUnbox* unbox);
     void visitReturn(MReturn* ret);
-    void lowerPhi(MPhi* phi);
-    void visitGuardShape(MGuardShape* ins);
-    void visitGuardObjectGroup(MGuardObjectGroup* ins);
-    void visitAsmJSUnsignedToDouble(MAsmJSUnsignedToDouble* ins);
-    void visitAsmJSUnsignedToFloat32(MAsmJSUnsignedToFloat32* ins);
-    void visitAsmJSLoadHeap(MAsmJSLoadHeap* ins);
-    void visitAsmJSStoreHeap(MAsmJSStoreHeap* ins);
-    void visitAsmJSCompareExchangeHeap(MAsmJSCompareExchangeHeap* ins);
-    void visitAsmJSAtomicExchangeHeap(MAsmJSAtomicExchangeHeap* ins);
-    void visitAsmJSAtomicBinopHeap(MAsmJSAtomicBinopHeap* ins);
-    void visitAsmJSLoadFuncPtr(MAsmJSLoadFuncPtr* ins);
-    void visitStoreTypedArrayElementStatic(MStoreTypedArrayElementStatic* ins);
-    void visitSimdBinaryArith(MSimdBinaryArith* ins);
-    void visitSimdSelect(MSimdSelect* ins);
-    void visitSimdSplatX4(MSimdSplatX4* ins);
-    void visitSimdValueX4(MSimdValueX4* ins);
-    void visitCompareExchangeTypedArrayElement(MCompareExchangeTypedArrayElement* ins);
-    void visitAtomicExchangeTypedArrayElement(MAtomicExchangeTypedArrayElement* ins);
-    void visitAtomicTypedArrayElementBinop(MAtomicTypedArrayElementBinop* ins);
-    void visitSubstr(MSubstr* ins);
-    void visitRandom(MRandom* ins);
 };
 
 typedef LIRGeneratorMIPS LIRGeneratorSpecific;
 
 } // namespace jit
 } // namespace js
 
 #endif /* jit_mips32_Lowering_mips32_h */
--- a/js/src/moz.build
+++ b/js/src/moz.build
@@ -463,16 +463,17 @@ elif CONFIG['JS_CODEGEN_ARM64']:
             'jit/arm64/vixl/Debugger-vixl.cpp',
             'jit/arm64/vixl/MozSimulator-vixl.cpp',
             'jit/arm64/vixl/Simulator-vixl.cpp'
         ]
 elif CONFIG['JS_CODEGEN_MIPS32']:
     UNIFIED_SOURCES += [
         'jit/mips-shared/Architecture-mips-shared.cpp',
         'jit/mips-shared/Assembler-mips-shared.cpp',
+        'jit/mips-shared/Lowering-mips-shared.cpp',
     ]
     if CONFIG['JS_CODEGEN_MIPS32']:
         UNIFIED_SOURCES += [
             'jit/mips32/Architecture-mips32.cpp',
             'jit/mips32/Assembler-mips32.cpp',
             'jit/mips32/Bailouts-mips32.cpp',
             'jit/mips32/BaselineCompiler-mips32.cpp',
             'jit/mips32/BaselineIC-mips32.cpp',
--- a/layout/base/nsRefreshDriver.cpp
+++ b/layout/base/nsRefreshDriver.cpp
@@ -73,17 +73,16 @@
 using namespace mozilla;
 using namespace mozilla::widget;
 using namespace mozilla::ipc;
 using namespace mozilla::layout;
 
 static PRLogModuleInfo *gLog = nullptr;
 #define LOG(...) MOZ_LOG(gLog, mozilla::LogLevel::Debug, (__VA_ARGS__))
 
-#define DEFAULT_FRAME_RATE 60
 #define DEFAULT_THROTTLED_FRAME_RATE 1
 #define DEFAULT_RECOMPUTE_VISIBILITY_INTERVAL_MS 1000
 // after 10 minutes, stop firing off inactive timers
 #define DEFAULT_INACTIVE_TIMER_DISABLE_SECONDS 600
 
 namespace mozilla {
 
 /*
@@ -760,33 +759,33 @@ nsRefreshDriver::Shutdown()
     timeEndPeriod(1);
   }
 #endif
 }
 
 /* static */ int32_t
 nsRefreshDriver::DefaultInterval()
 {
-  return NSToIntRound(1000.0 / DEFAULT_FRAME_RATE);
+  return NSToIntRound(1000.0 / gfxPlatform::GetDefaultFrameRate());
 }
 
 // Compute the interval to use for the refresh driver timer, in milliseconds.
 // outIsDefault indicates that rate was not explicitly set by the user
 // so we might choose other, more appropriate rates (e.g. vsync, etc)
 // layout.frame_rate=0 indicates "ASAP mode".
 // In ASAP mode rendering is iterated as fast as possible (typically for stress testing).
 // A target rate of 10k is used internally instead of special-handling 0.
 // Backends which block on swap/present/etc should try to not block
 // when layout.frame_rate=0 - to comply with "ASAP" as much as possible.
 double
 nsRefreshDriver::GetRegularTimerInterval(bool *outIsDefault) const
 {
   int32_t rate = Preferences::GetInt("layout.frame_rate", -1);
   if (rate < 0) {
-    rate = DEFAULT_FRAME_RATE;
+    rate = gfxPlatform::GetDefaultFrameRate();
     if (outIsDefault) {
       *outIsDefault = true;
     }
   } else {
     if (outIsDefault) {
       *outIsDefault = false;
     }
   }
--- a/media/mtransport/nricectx.h
+++ b/media/mtransport/nricectx.h
@@ -169,30 +169,31 @@ class NrIceTurnServer : public NrIceStun
       NrIceStunServer(transport), username_(username), password_(password) {}
 
   std::string username_;
   std::vector<unsigned char> password_;
 };
 
 class NrIceProxyServer {
  public:
-  NrIceProxyServer() :
-    host_(), port_(0) {
+  NrIceProxyServer(const std::string& host, uint16_t port,
+                   const std::string& alpn) :
+    host_(host), port_(port), alpn_(alpn) {
   }
 
-  NrIceProxyServer(const std::string& host, uint16_t port) :
-    host_(host), port_(port) {
-  }
+  NrIceProxyServer() : NrIceProxyServer("", 0, "") {}
 
   const std::string& host() const { return host_; }
   uint16_t port() const { return port_; }
+  const std::string& alpn() const { return alpn_; }
 
  private:
   std::string host_;
   uint16_t port_;
+  std::string alpn_;
 };
 
 
 class NrIceCtx {
  public:
   enum ConnectionState { ICE_CTX_INIT,
                          ICE_CTX_CHECKING,
                          ICE_CTX_OPEN,
--- a/media/mtransport/test/proxy_tunnel_socket_unittest.cpp
+++ b/media/mtransport/test/proxy_tunnel_socket_unittest.cpp
@@ -41,19 +41,23 @@ const uint16_t kRemotePort = 3333;
 
 const std::string kProxyHost = "example.com";
 const std::string kProxyAddr = "192.0.2.134";
 const uint16_t kProxyPort = 9999;
 
 const std::string kHelloMessage = "HELLO";
 const std::string kGarbageMessage = "xxxxxxxxxx";
 
-std::string connect_message(const std::string &host, uint16_t port, const std::string &tail = "") {
+std::string connect_message(const std::string &host, uint16_t port, const std::string &alpn, const std::string &tail) {
   std::stringstream ss;
-  ss << "CONNECT " << host << ":" << port << " HTTP/1.0\r\n\r\n" << tail;
+  ss << "CONNECT " << host << ":" << port << " HTTP/1.0\r\n";
+  if (!alpn.empty()) {
+    ss << "ALPN: " << alpn << "\r\n";
+  }
+  ss << "\r\n" << tail;
   return ss.str();
 }
 
 std::string connect_response(int code, const std::string &tail = "") {
   std::stringstream ss;
   ss << "HTTP/1.0 " << code << "\r\n\r\n" << tail;
   return ss.str();
 }
@@ -111,41 +115,60 @@ class ProxyTunnelSocketTest : public ::t
         nr_socket_(nullptr) {}
 
   ~ProxyTunnelSocketTest() {
     nr_socket_destroy(&nr_socket_);
     nr_proxy_tunnel_config_destroy(&config_);
   }
 
   void SetUp() {
-    nsRefPtr<DummySocket> dummy(new DummySocket());
-
     nr_resolver_ = resolver_impl_.get_nr_resolver();
 
     int r = nr_str_port_to_transport_addr(
         (char *)kRemoteAddr.c_str(), kRemotePort, IPPROTO_TCP, &remote_addr_);
     ASSERT_EQ(0, r);
 
     r = nr_str_port_to_transport_addr(
         (char *)kProxyAddr.c_str(), kProxyPort, IPPROTO_TCP, &proxy_addr_);
     ASSERT_EQ(0, r);
 
     nr_proxy_tunnel_config_create(&config_);
     nr_proxy_tunnel_config_set_resolver(config_, nr_resolver_);
     nr_proxy_tunnel_config_set_proxy(config_, kProxyAddr.c_str(), kProxyPort);
 
-    r = nr_socket_proxy_tunnel_create(
+    Configure();
+  }
+
+  // This reconfigures the socket with the updated information in config_.
+  void Configure() {
+    if (nr_socket_) {
+      EXPECT_EQ(0, nr_socket_destroy(&nr_socket_));
+      EXPECT_EQ(nullptr, nr_socket_);
+    }
+
+    nsRefPtr<DummySocket> dummy(new DummySocket());
+    int r = nr_socket_proxy_tunnel_create(
         config_,
         dummy->get_nr_socket(),
         &nr_socket_);
     ASSERT_EQ(0, r);
 
     socket_impl_ = dummy.forget();  // Now owned by nr_socket_.
   }
 
+  void Connect(int expectedReturn = 0) {
+    int r = nr_socket_connect(nr_socket_, &remote_addr_);
+    EXPECT_EQ(expectedReturn, r);
+
+    size_t written = 0;
+    r = nr_socket_write(nr_socket_, kHelloMessage.c_str(), kHelloMessage.size(), &written, 0);
+    EXPECT_EQ(0, r);
+    EXPECT_EQ(kHelloMessage.size(), written);
+  }
+
   nr_socket *socket() { return nr_socket_; }
 
  protected:
   nsRefPtr<DummySocket> socket_impl_;
   DummyResolver resolver_impl_;
   nr_socket *nr_socket_;
   nr_resolver *nr_resolver_;
   nr_proxy_tunnel_config *config_;
@@ -161,66 +184,77 @@ TEST_F(ProxyTunnelSocketTest, TestConnec
   int r = nr_socket_connect(nr_socket_, &remote_addr_);
   ASSERT_EQ(0, r);
 
   ASSERT_EQ(0, nr_transport_addr_cmp(socket_impl_->get_connect_addr(), &proxy_addr_,
         NR_TRANSPORT_ADDR_CMP_MODE_ALL));
 }
 
 TEST_F(ProxyTunnelSocketTest, TestConnectProxyRequest) {
-  int r = nr_socket_connect(nr_socket_, &remote_addr_);
-  ASSERT_EQ(0, r);
+  Connect();
+
+  std::string msg = connect_message(kRemoteAddr, kRemotePort, "", kHelloMessage);
+  socket_impl_->CheckWriteBuffer(reinterpret_cast<const uint8_t *>(msg.c_str()), msg.size());
+}
+
+TEST_F(ProxyTunnelSocketTest, TestAlpnConnect) {
+  const std::string alpn = "this,is,alpn";
+  int r = nr_proxy_tunnel_config_set_alpn(config_, alpn.c_str());
+  EXPECT_EQ(0, r);
 
-  size_t written = 0;
-  r = nr_socket_write(nr_socket_, kHelloMessage.c_str(), kHelloMessage.size(), &written, 0);
-  ASSERT_EQ(0, r);
+  Configure();
+  Connect();
+
+  std::string msg = connect_message(kRemoteAddr, kRemotePort, alpn, kHelloMessage);
+  socket_impl_->CheckWriteBuffer(reinterpret_cast<const uint8_t *>(msg.c_str()), msg.size());
+}
 
-  std::string msg = connect_message(kRemoteAddr, kRemotePort, kHelloMessage);
+TEST_F(ProxyTunnelSocketTest, TestNullAlpnConnect) {
+  int r = nr_proxy_tunnel_config_set_alpn(config_, nullptr);
+  EXPECT_EQ(0, r);
+
+  Configure();
+  Connect();
+
+  std::string msg = connect_message(kRemoteAddr, kRemotePort, "", kHelloMessage);
   socket_impl_->CheckWriteBuffer(reinterpret_cast<const uint8_t *>(msg.c_str()), msg.size());
 }
 
 TEST_F(ProxyTunnelSocketTest, TestConnectProxyHostRequest) {
-  int r = nr_socket_destroy(&nr_socket_);
-  ASSERT_EQ(0, r);
-
-  nsRefPtr<DummySocket> dummy(new DummySocket());
-
   nr_proxy_tunnel_config_set_proxy(config_, kProxyHost.c_str(), kProxyPort);
+  Configure();
+  // Because kProxyHost is a domain name and not an IP address,
+  // nr_socket_connect will need to resolve an IP address before continuing.  It
+  // does that, and assumes that resolving the IP will take some time, so it
+  // returns R_WOULDBLOCK.
+  //
+  // However, In this test setup, the resolution happens inline immediately, so
+  // nr_socket_connect is called recursively on the inner socket in
+  // nr_socket_proxy_tunnel_resolved_cb.  That also completes.  Thus, the socket
+  // is actually successfully connected after this call, even though
+  // nr_socket_connect reports an error.
+  //
+  // Arguably nr_socket_proxy_tunnel_connect() is busted, because it shouldn't
+  // report an error when it doesn't need any further assistance from the
+  // calling code, but that's pretty minor.
+  Connect(R_WOULDBLOCK);
 
-  r = nr_socket_proxy_tunnel_create(
-      config_,
-      dummy->get_nr_socket(),
-      &nr_socket_);
-  ASSERT_EQ(0, r);
-
-  socket_impl_ = dummy.forget();  // Now owned by nr_socket_.
-
-  r = nr_socket_connect(nr_socket_, &remote_addr_);
-  ASSERT_EQ(R_WOULDBLOCK, r);
-
-  size_t written = 0;
-  r = nr_socket_write(nr_socket_, kHelloMessage.c_str(), kHelloMessage.size(), &written, 0);
-  ASSERT_EQ(0, r);
-
-  std::string msg = connect_message(kRemoteAddr, kRemotePort, kHelloMessage);
+  std::string msg = connect_message(kRemoteAddr, kRemotePort, "", kHelloMessage);
   socket_impl_->CheckWriteBuffer(reinterpret_cast<const uint8_t *>(msg.c_str()), msg.size());
 }
 
 TEST_F(ProxyTunnelSocketTest, TestConnectProxyWrite) {
-  int r = nr_socket_connect(nr_socket_, &remote_addr_);
-  ASSERT_EQ(0, r);
-
-  size_t written = 0;
-  r = nr_socket_write(nr_socket_, kHelloMessage.c_str(), kHelloMessage.size(), &written, 0);
-  ASSERT_EQ(0, r);
+  Connect();
 
   socket_impl_->ClearWriteBuffer();
 
-  r = nr_socket_write(nr_socket_, kHelloMessage.c_str(), kHelloMessage.size(), &written, 0);
-  ASSERT_EQ(0, r);
+  size_t written = 0;
+  int r = nr_socket_write(nr_socket_, kHelloMessage.c_str(), kHelloMessage.size(), &written, 0);
+  EXPECT_EQ(0, r);
+  EXPECT_EQ(kHelloMessage.size(), written);
 
   socket_impl_->CheckWriteBuffer(reinterpret_cast<const uint8_t *>(kHelloMessage.c_str()),
       kHelloMessage.size());
 }
 
 TEST_F(ProxyTunnelSocketTest, TestConnectProxySuccessResponse) {
   int r = nr_socket_connect(nr_socket_, &remote_addr_);
   ASSERT_EQ(0, r);
--- a/media/mtransport/third_party/nICEr/src/net/nr_proxy_tunnel.c
+++ b/media/mtransport/third_party/nICEr/src/net/nr_proxy_tunnel.c
@@ -36,17 +36,21 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 #include <nr_api.h>
 
 #include <assert.h>
 
 #include "nr_proxy_tunnel.h"
 
 #define MAX_HTTP_CONNECT_ADDR_SIZE 256
 #define MAX_HTTP_CONNECT_BUFFER_SIZE 1024
-#define ENDLN "\r\n\r\n"
+#define MAX_ALPN_LENGTH 64
+#ifndef CRLF
+#define CRLF "\r\n"
+#endif
+#define END_HEADERS CRLF CRLF
 
 typedef struct nr_socket_proxy_tunnel_ {
   nr_proxy_tunnel_config *config;
   nr_socket *inner;
   nr_transport_addr remote_addr;
   int connect_requested;
   int connect_answered;
   int connect_failed;
@@ -89,59 +93,76 @@ static nr_socket_vtbl nr_socket_proxy_tu
 };
 
 static int send_http_connect(nr_socket_proxy_tunnel *sock)
 {
   int r, _status;
   int port;
   int printed;
   char addr[MAX_HTTP_CONNECT_ADDR_SIZE];
-  char mesg[MAX_HTTP_CONNECT_ADDR_SIZE + 64];
+  char mesg[MAX_HTTP_CONNECT_ADDR_SIZE + MAX_ALPN_LENGTH + 128];
+  size_t offset = 0;
   size_t bytes_sent;
 
   r_log(LOG_GENERIC,LOG_DEBUG,"send_http_connect");
 
   if ((r=nr_transport_addr_get_port(&sock->remote_addr, &port))) {
     ABORT(r);
   }
 
   if ((r=nr_transport_addr_get_addrstring(&sock->remote_addr, addr, sizeof(addr)))) {
     ABORT(r);
   }
 
-  printed = snprintf(mesg, sizeof(mesg), "CONNECT %s:%d HTTP/1.0%s", addr, port, ENDLN);
-  if (printed < 0 || ((size_t)printed >= sizeof(mesg))) {
+  printed = snprintf(mesg + offset, sizeof(mesg) - offset,
+                     "CONNECT %s:%d HTTP/1.0", addr, port);
+  offset += printed;
+  if (printed < 0 || (offset >= sizeof(mesg))) {
     ABORT(R_FAILED);
   }
 
-  if ((r=nr_socket_write(sock->inner, mesg, strlen(mesg), &bytes_sent, 0))) {
+  if (sock->config->alpn) {
+    printed = snprintf(mesg + offset, sizeof(mesg) - offset,
+                       CRLF "ALPN: %s", sock->config->alpn);
+    offset += printed;
+    if (printed < 0 || (offset >= sizeof(mesg))) {
+      ABORT(R_FAILED);
+    }
+  }
+  if (offset + sizeof(END_HEADERS) >= sizeof(mesg)) {
+    ABORT(R_FAILED);
+  }
+  memcpy(mesg + offset, END_HEADERS, strlen(END_HEADERS));
+  offset += strlen(END_HEADERS);
+
+  if ((r=nr_socket_write(sock->inner, mesg, offset, &bytes_sent, 0))) {
     ABORT(r);
   }
 
-  if (bytes_sent < strlen(mesg)) {
+  if (bytes_sent < offset) {
     /* TODO(bug 1116583): buffering and wait for */
     r_log(LOG_GENERIC,LOG_DEBUG,"send_http_connect should be buffering %lu", (unsigned long)bytes_sent);
     ABORT(R_IO_ERROR);
   }
 
   sock->connect_requested = 1;
 
   _status = 0;
 abort:
   return(_status);
 }
 
 static char *find_http_terminator(char *response, size_t len)
 {
   char *term = response;
   char *end = response + len;
-  int N = strlen(ENDLN);
+  int N = strlen(END_HEADERS);
 
   for (; term = memchr(term, '\r', end - term); ++term) {
-    if (end - term >= N && memcmp(term, ENDLN, N) == 0) {
+    if (end - term >= N && memcmp(term, END_HEADERS, N) == 0) {
       return term;
     }
   }
 
   return NULL;
 }
 
 static int parse_http_response(char *begin, char *end, unsigned int *status)
@@ -362,17 +383,17 @@ int nr_socket_proxy_tunnel_read(void *ob
 
     /* TODO (bug 1115934): Handle authentication challenges. */
     if (http_status < 200 || http_status >= 300) {
       r_log(LOG_GENERIC,LOG_ERR,"nr_socket_proxy_tunnel_read unable to connect %u",
             http_status);
       ABORT(R_FAILED);
     }
 
-    ptr = http_term + strlen(ENDLN);
+    ptr = http_term + strlen(END_HEADERS);
     pending = sock->buffered_bytes - (ptr - sock->buffer);
 
     if (pending == 0) {
       ABORT(R_WOULDBLOCK);
     }
 
     assert(pending <= maxlen);
     *len = pending;
@@ -426,16 +447,17 @@ int nr_proxy_tunnel_config_destroy(nr_pr
 
   if (!configpp || !*configpp)
     return 0;
 
   configp = *configpp;
   *configpp = 0;
 
   RFREE(configp->proxy_host);
+  RFREE(configp->alpn);
   RFREE(configp);
 
   return 0;
 }
 
 int nr_proxy_tunnel_config_set_proxy(nr_proxy_tunnel_config *config,
                                      const char *host, UINT2 port)
 {
@@ -466,30 +488,61 @@ int nr_proxy_tunnel_config_set_resolver(
 {
   r_log(LOG_GENERIC,LOG_DEBUG,"nr_proxy_tunnel_config_set_resolver");
 
   config->resolver = resolver;
 
   return 0;
 }
 
+int nr_proxy_tunnel_config_set_alpn(nr_proxy_tunnel_config *config,
+                                    const char *alpn)
+{
+  r_log(LOG_GENERIC,LOG_DEBUG,"nr_proxy_tunnel_config_set_alpn");
+
+  if (alpn && (strlen(alpn) > MAX_ALPN_LENGTH)) {
+    return R_BAD_ARGS;
+  }
+
+  if (config->alpn) {
+    RFREE(config->alpn);
+  }
+
+  config->alpn = NULL;
+
+  if (alpn) {
+    char *alpndup = r_strdup(alpn);
+
+    if (!alpndup) {
+      return R_NO_MEMORY;
+    }
+
+    config->alpn = alpndup;
+  }
+
+  return 0;
+}
+
 int nr_proxy_tunnel_config_copy(nr_proxy_tunnel_config *config, nr_proxy_tunnel_config **copypp)
 {
   int r,_status;
   nr_proxy_tunnel_config *copy = 0;
 
   if ((r=nr_proxy_tunnel_config_create(&copy)))
     ABORT(r);
 
   if ((r=nr_proxy_tunnel_config_set_proxy(copy, config->proxy_host, config->proxy_port)))
     ABORT(r);
 
   if ((r=nr_proxy_tunnel_config_set_resolver(copy, config->resolver)))
     ABORT(r);
 
+  if ((r=nr_proxy_tunnel_config_set_alpn(copy, config->alpn)))
+    ABORT(r);
+
   *copypp = copy;
 
   _status=0;
 abort:
   if (_status) {
     nr_proxy_tunnel_config_destroy(&copy);
   }
   return(_status);
--- a/media/mtransport/third_party/nICEr/src/net/nr_proxy_tunnel.h
+++ b/media/mtransport/third_party/nICEr/src/net/nr_proxy_tunnel.h
@@ -39,28 +39,32 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 #include "nr_socket.h"
 #include "nr_resolver.h"
 #include "nr_socket_wrapper.h"
 
 typedef struct nr_proxy_tunnel_config_ {
   nr_resolver *resolver;
   char *proxy_host;
   UINT2 proxy_port;
+  char *alpn;
 } nr_proxy_tunnel_config;
 
 int nr_proxy_tunnel_config_create(nr_proxy_tunnel_config **config);
 
 int nr_proxy_tunnel_config_destroy(nr_proxy_tunnel_config **config);
 
 int nr_proxy_tunnel_config_set_proxy(nr_proxy_tunnel_config *config,
                                      const char* host, UINT2 port);
 
 int nr_proxy_tunnel_config_set_resolver(nr_proxy_tunnel_config *config,
                                         nr_resolver *resolver);
 
+int nr_proxy_tunnel_config_set_alpn(nr_proxy_tunnel_config *config,
+                                    const char *alpn);
+
 int nr_socket_proxy_tunnel_create(nr_proxy_tunnel_config *config,
                                   nr_socket *inner,
                                   nr_socket **socketpp);
 
 int nr_socket_wrapper_factory_proxy_tunnel_create(nr_proxy_tunnel_config *config,
                                                   nr_socket_wrapper_factory **factory);
 
 #endif
--- a/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.cpp
+++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.cpp
@@ -200,19 +200,25 @@ PeerConnectionMedia::ProtocolProxyQueryH
   rv = proxyinfo.GetPort(&httpsProxyPort);
   if (NS_FAILED(rv)) {
     CSFLogError(logTag, "%s: Failed to get proxy server port", __FUNCTION__);
     return;
   }
 
   if (pcm_->mIceCtx.get()) {
     assert(httpsProxyPort >= 0 && httpsProxyPort < (1 << 16));
+    // Note that this could check if PrivacyRequested() is set on the PC and
+    // remove "webrtc" from the ALPN list.  But that would only work if the PC
+    // was constructed with a peerIdentity constraint, not when isolated
+    // streams are added.  If we ever need to signal to the proxy that the
+    // media is isolated, then we would need to restructure this code.
     pcm_->mProxyServer.reset(
       new NrIceProxyServer(httpsProxyHost.get(),
-                           static_cast<uint16_t>(httpsProxyPort)));
+                           static_cast<uint16_t>(httpsProxyPort),
+                           "webrtc,c-webrtc"));
   } else {
     CSFLogError(logTag, "%s: Failed to set proxy server (ICE ctx unavailable)",
         __FUNCTION__);
   }
 }
 
 NS_IMPL_ISUPPORTS(PeerConnectionMedia::ProtocolProxyQueryHandler, nsIProtocolProxyCallback)
 #endif // !defined(MOZILLA_XPCOMRT_API)
--- a/memory/build/jemalloc_config.cpp
+++ b/memory/build/jemalloc_config.cpp
@@ -116,17 +116,17 @@ private:
   static bool
   CommitHook(void* chunk, size_t size, size_t offset, size_t length,
              unsigned arena_ind)
   {
     void* addr = reinterpret_cast<void*>(
       reinterpret_cast<uintptr_t>(chunk) + static_cast<uintptr_t>(offset));
 
     if (!VirtualAlloc(addr, length, MEM_COMMIT, PAGE_READWRITE))
-      MOZ_CRASH();
+      return true;
 
     return false;
   }
 
   static bool
   DecommitHook(void* chunk, size_t size, size_t offset, size_t length,
                unsigned arena_ind)
   {
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -1455,20 +1455,16 @@ pref("network.http.packaged-apps-develop
 
 // default values for FTP
 // in a DSCP environment this should be 40 (0x28, or AF11), per RFC-4594,
 // Section 4.8 "High-Throughput Data Service Class", and 80 (0x50, or AF22)
 // per Section 4.7 "Low-Latency Data Service Class".
 pref("network.ftp.data.qos", 0);
 pref("network.ftp.control.qos", 0);
 
-// If this pref is false only one xpcom event will be served per poll
-// iteration. This is the original behavior.
-// If it is true multiple events will be served.
-pref("network.sts.serve_multiple_events_per_poll_iteration", true);
 // The max time to spend on xpcom events between two polls in ms.
 pref("network.sts.max_time_for_events_between_two_polls", 100);
 // </http>
 
 // 2147483647 == PR_INT32_MAX == ~2 GB
 pref("network.websocket.max-message-size", 2147483647);
 
 // Should we automatically follow http 3xx redirects during handshake
--- a/netwerk/base/nsIUploadChannel2.idl
+++ b/netwerk/base/nsIUploadChannel2.idl
@@ -1,18 +1,19 @@
 /* -*- Mode: C++; tab-width: 4; 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 "nsISupports.idl"
 
 interface nsIInputStream;
+interface nsIRunnable;
 
-[scriptable, uuid(62e6529a-5cf6-491a-82ef-b3a8273cdd19)]
+[scriptable, uuid(2f712b52-19c5-4e0c-9e8f-b5c7c3b67049)]
 interface nsIUploadChannel2 : nsISupports
 {
     /**
      * Sets a stream to be uploaded by this channel with the specified
      * Content-Type and Content-Length header values.
      *
      * Most implementations of this interface require that the stream:
      *   (1) implement threadsafe addRef and release
@@ -42,13 +43,25 @@ interface nsIUploadChannel2 : nsISupport
     /**
      * Value of aStreamHasHeaders from the last successful call to
      * explicitSetUploadStream.  TRUE indicates the attached upload stream
      * contians request headers.
      */
     readonly attribute boolean uploadStreamHasHeaders;
 
     /**
-     * Clones the upload stream and returns an equivalent stream.
+     * Ensure the upload stream, if any, is cloneable.  This may involve
+     * async copying, so a callback runnable must be provided.  It will
+     * invoked on the current thread when the upload stream is ready
+     * for cloning.  If the stream is already cloneable, then the callback
+     * will be invoked synchronously.
+     */
+    [noscript]
+    void ensureUploadStreamIsCloneable(in nsIRunnable aCallback);
+
+    /**
+     * Clones the upload stream.  May return failure if the upload stream
+     * is not cloneable.  If this is not acceptable, use the
+     * ensureUploadStreamIsCloneable() method first.
      */
     [noscript]
     nsIInputStream cloneUploadStream();
 };
--- a/netwerk/base/nsSocketTransportService2.cpp
+++ b/netwerk/base/nsSocketTransportService2.cpp
@@ -39,17 +39,16 @@ PRThread                 *gSocketThread 
 #define SEND_BUFFER_PREF "network.tcp.sendbuffer"
 #define KEEPALIVE_ENABLED_PREF "network.tcp.keepalive.enabled"
 #define KEEPALIVE_IDLE_TIME_PREF "network.tcp.keepalive.idle_time"
 #define KEEPALIVE_RETRY_INTERVAL_PREF "network.tcp.keepalive.retry_interval"
 #define KEEPALIVE_PROBE_COUNT_PREF "network.tcp.keepalive.probe_count"
 #define SOCKET_LIMIT_TARGET 550U
 #define SOCKET_LIMIT_MIN     50U
 #define BLIP_INTERVAL_PREF "network.activity.blipIntervalMilliseconds"
-#define SERVE_MULTIPLE_EVENTS_PREF "network.sts.serve_multiple_events_per_poll_iteration"
 #define MAX_TIME_BETWEEN_TWO_POLLS "network.sts.max_time_for_events_between_two_polls"
 #define TELEMETRY_PREF "toolkit.telemetry.enabled"
 
 uint32_t nsSocketTransportService::gMaxCount;
 PRCallOnceType nsSocketTransportService::gMaxCountInitOnce;
 
 class DebugMutexAutoLock
 {
@@ -101,17 +100,16 @@ nsSocketTransportService::nsSocketTransp
     , mIdleCount(0)
     , mSentBytesCount(0)
     , mReceivedBytesCount(0)
     , mSendBufferSize(0)
     , mKeepaliveIdleTimeS(600)
     , mKeepaliveRetryIntervalS(1)
     , mKeepaliveProbeCount(kDefaultTCPKeepCount)
     , mKeepaliveEnabledPref(false)
-    , mServeMultipleEventsPerPollIter(true)
     , mServingPendingQueue(false)
     , mMaxTimePerPollIter(100)
     , mTelemetryEnabledPref(false)
     , mProbedMaxCount(false)
 {
     gSocketTransportLog = PR_NewLogModule("nsSocketTransport");
     gUDPSocketLog = PR_NewLogModule("UDPSocket");
 
@@ -538,17 +536,16 @@ nsSocketTransportService::Init()
 
     nsCOMPtr<nsIPrefBranch> tmpPrefService = do_GetService(NS_PREFSERVICE_CONTRACTID);
     if (tmpPrefService) {
         tmpPrefService->AddObserver(SEND_BUFFER_PREF, this, false);
         tmpPrefService->AddObserver(KEEPALIVE_ENABLED_PREF, this, false);
         tmpPrefService->AddObserver(KEEPALIVE_IDLE_TIME_PREF, this, false);
         tmpPrefService->AddObserver(KEEPALIVE_RETRY_INTERVAL_PREF, this, false);
         tmpPrefService->AddObserver(KEEPALIVE_PROBE_COUNT_PREF, this, false);
-        tmpPrefService->AddObserver(SERVE_MULTIPLE_EVENTS_PREF, this, false);
         tmpPrefService->AddObserver(MAX_TIME_BETWEEN_TWO_POLLS, this, false);
         tmpPrefService->AddObserver(TELEMETRY_PREF, this, false);
     }
     UpdatePrefs();
 
     nsCOMPtr<nsIObserverService> obsSvc = services::GetObserverService();
     if (obsSvc) {
         obsSvc->AddObserver(this, "profile-initial-state", false);
@@ -880,67 +877,61 @@ nsSocketTransportService::Run()
             }
 
             // If nothing was pending before the poll, it might be now
             if (!pendingEvents) {
                 thread->HasPendingEvents(&pendingEvents);
             }
 
             if (pendingEvents) {
-                if (mServeMultipleEventsPerPollIter) {
-                    if (!mServingPendingQueue) {
-                        nsresult rv = Dispatch(NS_NewRunnableMethod(this,
-                            &nsSocketTransportService::MarkTheLastElementOfPendingQueue),
-                            nsIEventTarget::DISPATCH_NORMAL);
-                        if (NS_FAILED(rv)) {
-                            NS_WARNING("Could not dispatch a new event on the "
-                                       "socket thread.");
-                        } else {
-                            mServingPendingQueue = true;
-                        }
-
-                        if (mTelemetryEnabledPref) {
-                            startOfIteration = startOfNextIteration;
-                            // Everything that comes after this point will
-                            // be served in the next iteration. If no even
-                            // arrives, startOfNextIteration will be reset at the
-                            // beginning of each for-loop.
-                            startOfNextIteration = TimeStamp::NowLoRes();
-                        }
+                if (!mServingPendingQueue) {
+                    nsresult rv = Dispatch(NS_NewRunnableMethod(this,
+                        &nsSocketTransportService::MarkTheLastElementOfPendingQueue),
+                        nsIEventTarget::DISPATCH_NORMAL);
+                    if (NS_FAILED(rv)) {
+                        NS_WARNING("Could not dispatch a new event on the "
+                                   "socket thread.");
+                    } else {
+                        mServingPendingQueue = true;
                     }
-                    TimeStamp eventQueueStart = TimeStamp::NowLoRes();
-                    do {
-                        NS_ProcessNextEvent(thread);
-                        numberOfPendingEvents++;
-                        pendingEvents = false;
-                        thread->HasPendingEvents(&pendingEvents);
-                    } while (pendingEvents && mServingPendingQueue &&
-                             ((TimeStamp::NowLoRes() -
-                               eventQueueStart).ToMilliseconds() <
-                              mMaxTimePerPollIter));
 
-                    if (mTelemetryEnabledPref && !mServingPendingQueue &&
-                        !startOfIteration.IsNull()) {
-                        Telemetry::AccumulateTimeDelta(
-                            Telemetry::STS_POLL_AND_EVENTS_CYCLE,
-                            startOfIteration + pollDuration,
-                            TimeStamp::NowLoRes());
-
-                        Telemetry::Accumulate(
-                            Telemetry::STS_NUMBER_OF_PENDING_EVENTS,
-                            numberOfPendingEvents);
-
-                        numberOfPendingEventsLastCycle += numberOfPendingEvents;
-                        numberOfPendingEvents = 0;
-                        pollDuration = 0;
+                    if (mTelemetryEnabledPref) {
+                        startOfIteration = startOfNextIteration;
+                        // Everything that comes after this point will
+                        // be served in the next iteration. If no even
+                        // arrives, startOfNextIteration will be reset at the
+                        // beginning of each for-loop.
+                        startOfNextIteration = TimeStamp::NowLoRes();
                     }
-                } else {
+                }
+                TimeStamp eventQueueStart = TimeStamp::NowLoRes();
+                do {
                     NS_ProcessNextEvent(thread);
+                    numberOfPendingEvents++;
                     pendingEvents = false;
                     thread->HasPendingEvents(&pendingEvents);
+                } while (pendingEvents && mServingPendingQueue &&
+                         ((TimeStamp::NowLoRes() -
+                           eventQueueStart).ToMilliseconds() <
+                          mMaxTimePerPollIter));
+
+                if (mTelemetryEnabledPref && !mServingPendingQueue &&
+                    !startOfIteration.IsNull()) {
+                    Telemetry::AccumulateTimeDelta(
+                        Telemetry::STS_POLL_AND_EVENTS_CYCLE,
+                        startOfIteration + pollDuration,
+                        TimeStamp::NowLoRes());
+
+                    Telemetry::Accumulate(
+                        Telemetry::STS_NUMBER_OF_PENDING_EVENTS,
+                        numberOfPendingEvents);
+
+                    numberOfPendingEventsLastCycle += numberOfPendingEvents;
+                    numberOfPendingEvents = 0;
+                    pollDuration = 0;
                 }
             }
         } while (pendingEvents);
 
         bool goingOffline = false;
         // now that our event queue is empty, check to see if we should exit
         {
             DebugMutexAutoLock lock(mLock);
@@ -1201,23 +1192,16 @@ nsSocketTransportService::UpdatePrefs()
         bool keepaliveEnabled = false;
         rv = tmpPrefService->GetBoolPref(KEEPALIVE_ENABLED_PREF,
                                          &keepaliveEnabled);
         if (NS_SUCCEEDED(rv) && keepaliveEnabled != mKeepaliveEnabledPref) {
             mKeepaliveEnabledPref = keepaliveEnabled;
             OnKeepaliveEnabledPrefChange();
         }
 
-        bool serveMultiplePref = false;
-        rv = tmpPrefService->GetBoolPref(SERVE_MULTIPLE_EVENTS_PREF,
-                                         &serveMultiplePref);
-        if (NS_SUCCEEDED(rv)) {
-            mServeMultipleEventsPerPollIter = serveMultiplePref;
-        }
-
         int32_t maxTimePref;
         rv = tmpPrefService->GetIntPref(MAX_TIME_BETWEEN_TWO_POLLS,
                                         &maxTimePref);
         if (NS_SUCCEEDED(rv) && maxTimePref >= 0) {
             mMaxTimePerPollIter = maxTimePref;
         }
 
         bool telemetryPref = false;
--- a/netwerk/base/nsSocketTransportService2.h
+++ b/netwerk/base/nsSocketTransportService2.h
@@ -231,17 +231,16 @@ private:
     int32_t     mKeepaliveIdleTimeS;
     // Number of seconds between retries should keepalive pings fail.
     int32_t     mKeepaliveRetryIntervalS;
     // Number of keepalive probes to send.
     int32_t     mKeepaliveProbeCount;
     // True if TCP keepalive is enabled globally.
     bool        mKeepaliveEnabledPref;
 
-    bool                   mServeMultipleEventsPerPollIter;
     mozilla::Atomic<bool>  mServingPendingQueue;
     int32_t                mMaxTimePerPollIter;
     mozilla::Atomic<bool, mozilla::Relaxed>  mTelemetryEnabledPref;
 
     void OnKeepaliveEnabledPrefChange();
     void NotifyKeepaliveEnabledPrefChange(SocketContext *sock);
 
     // Socket thread only for dynamically adjusting max socket size
--- a/netwerk/protocol/http/HttpBaseChannel.cpp
+++ b/netwerk/protocol/http/HttpBaseChannel.cpp
@@ -14,16 +14,17 @@
 #include "nsMimeTypes.h"
 #include "nsNetCID.h"
 #include "nsNetUtil.h"
 
 #include "nsICachingChannel.h"
 #include "nsIPrincipal.h"
 #include "nsIScriptError.h"
 #include "nsISeekableStream.h"
+#include "nsIStorageStream.h"
 #include "nsITimedChannel.h"
 #include "nsIEncodedChannel.h"
 #include "nsIApplicationCacheChannel.h"
 #include "nsIMutableArray.h"
 #include "nsEscape.h"
 #include "nsStreamListenerWrapper.h"
 #include "nsISecurityConsoleMessage.h"
 #include "nsURLHelper.h"
@@ -569,55 +570,124 @@ HttpBaseChannel::SetUploadStream(nsIInpu
   // if stream is null, ExplicitSetUploadStream returns error.
   // So we need special case for GET method.
   mUploadStreamHasHeaders = false;
   mRequestHead.SetMethod(NS_LITERAL_CSTRING("GET")); // revert to GET request
   mUploadStream = stream;
   return NS_OK;
 }
 
-static void
-EnsureStreamBuffered(nsCOMPtr<nsIInputStream>& aStream)
+namespace {
+
+void
+CopyComplete(void* aClosure, nsresult aStatus) {
+  // Called on the STS thread by NS_AsyncCopy
+  auto channel = static_cast<HttpBaseChannel*>(aClosure);
+  nsCOMPtr<nsIRunnable> runnable = NS_NewRunnableMethodWithArg<nsresult>(
+    channel, &HttpBaseChannel::EnsureUploadStreamIsCloneableComplete, aStatus);
+  NS_DispatchToMainThread(runnable.forget());
+}
+
+} // anonymous namespace
+
+NS_IMETHODIMP
+HttpBaseChannel::EnsureUploadStreamIsCloneable(nsIRunnable* aCallback)
 {
-  if (!NS_InputStreamIsBuffered(aStream)) {
-    nsCOMPtr<nsIInputStream> bufferedStream;
-    nsresult rv = NS_NewBufferedInputStream(getter_AddRefs(bufferedStream),
-                                            aStream,
-                                            4096);
-    NS_ENSURE_SUCCESS_VOID(rv);
-    aStream.swap(bufferedStream);
+  MOZ_ASSERT(NS_IsMainThread(), "Should only be called on the main thread.");
+  NS_ENSURE_ARG_POINTER(aCallback);
+
+  // We could in theory allow multiple callers to use this method,
+  // but the complexity does not seem worth it yet.  Just fail if
+  // this is called more than once simultaneously.
+  NS_ENSURE_FALSE(mUploadCloneableCallback, NS_ERROR_UNEXPECTED);
+
+  // If the CloneUploadStream() will succeed, then synchronously invoke
+  // the callback to indicate we're already cloneable.
+  if (!mUploadStream || NS_InputStreamIsCloneable(mUploadStream)) {
+    aCallback->Run();
+    return NS_OK;
+  }
+
+  nsCOMPtr<nsIStorageStream> storageStream;
+  nsresult rv = NS_NewStorageStream(4096, UINT32_MAX,
+                                    getter_AddRefs(storageStream));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  nsCOMPtr<nsIInputStream> newUploadStream;
+  rv = storageStream->NewInputStream(0, getter_AddRefs(newUploadStream));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  nsCOMPtr<nsIOutputStream> sink;
+  rv = storageStream->GetOutputStream(0, getter_AddRefs(sink));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  nsCOMPtr<nsIInputStream> source;
+  if (NS_InputStreamIsBuffered(mUploadStream)) {
+    source = mUploadStream;
+  } else {
+    rv = NS_NewBufferedInputStream(getter_AddRefs(source), mUploadStream, 4096);
+    NS_ENSURE_SUCCESS(rv, rv);
   }
+
+  nsCOMPtr<nsIEventTarget> target =
+    do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
+
+  mUploadCloneableCallback = aCallback;
+
+  rv = NS_AsyncCopy(source, sink, target, NS_ASYNCCOPY_VIA_READSEGMENTS,
+                    4096, // copy segment size
+                    CopyComplete, this);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    mUploadCloneableCallback = nullptr;
+    return rv;
+  }
+
+  // Since we're consuming the old stream, replace it with the new
+  // stream immediately.
+  mUploadStream = newUploadStream;
+
+  // Explicity hold the stream alive until copying is complete.  This will
+  // be released in EnsureUploadStreamIsCloneableComplete().
+  AddRef();
+
+  return NS_OK;
+}
+
+void
+HttpBaseChannel::EnsureUploadStreamIsCloneableComplete(nsresult aStatus)
+{
+  MOZ_ASSERT(NS_IsMainThread(), "Should only be called on the main thread.");
+  MOZ_ASSERT(mUploadCloneableCallback);
+
+  if (NS_SUCCEEDED(mStatus)) {
+    mStatus = aStatus;
+  }
+
+  mUploadCloneableCallback->Run();
+  mUploadCloneableCallback = nullptr;
+
+  // Release the reference we grabbed in EnsureUploadStreamIsCloneable() now
+  // that the copying is complete.
+  Release();
 }
 
 NS_IMETHODIMP
 HttpBaseChannel::CloneUploadStream(nsIInputStream** aClonedStream)
 {
   NS_ENSURE_ARG_POINTER(aClonedStream);
   *aClonedStream = nullptr;
 
   if (!mUploadStream) {
     return NS_OK;
   }
 
   nsCOMPtr<nsIInputStream> clonedStream;
-  nsCOMPtr<nsIInputStream> replacementStream;
-  nsresult rv = NS_CloneInputStream(mUploadStream, getter_AddRefs(clonedStream),
-                                    getter_AddRefs(replacementStream));
+  nsresult rv = NS_CloneInputStream(mUploadStream, getter_AddRefs(clonedStream));
   NS_ENSURE_SUCCESS(rv, rv);
 
-  if (replacementStream) {
-    mUploadStream.swap(replacementStream);
-
-    // Ensure that the replacement stream is buffered.
-    EnsureStreamBuffered(mUploadStream);
-  }
-
-  // Ensure that the cloned stream is buffered.
-  EnsureStreamBuffered(clonedStream);
-
   clonedStream.forget(aClonedStream);
 
   return NS_OK;
 }
 
 
 //-----------------------------------------------------------------------------
 // HttpBaseChannel::nsIUploadChannel2
--- a/netwerk/protocol/http/HttpBaseChannel.h
+++ b/netwerk/protocol/http/HttpBaseChannel.h
@@ -264,16 +264,20 @@ public: /* Necko internal use only... */
     static bool ShouldRewriteRedirectToGET(uint32_t httpStatus,
                                            nsHttpRequestHead::ParsedMethodType method);
 
     // Like nsIEncodedChannel::DoApplyConversions except context is set to
     // mListenerContext.
     nsresult DoApplyContentConversions(nsIStreamListener *aNextListener,
                                        nsIStreamListener **aNewNextListener);
 
+    // Callback on main thread when NS_AsyncCopy() is finished populating
+    // the new mUploadStream.
+    void EnsureUploadStreamIsCloneableComplete(nsresult aStatus);
+
 protected:
   nsCOMArray<nsISecurityConsoleMessage> mSecurityConsoleMessages;
 
   // Handle notifying listener, removing from loadgroup if request failed.
   void     DoNotifyListener();
   virtual void DoNotifyListenerCleanup() = 0;
 
   // drop reference to listener, its callbacks, and the progress sink
@@ -324,16 +328,17 @@ protected:
   nsCOMPtr<nsILoadInfo>             mLoadInfo;
   nsCOMPtr<nsIInterfaceRequestor>   mCallbacks;
   nsCOMPtr<nsIProgressEventSink>    mProgressSink;
   nsCOMPtr<nsIURI>                  mReferrer;
   nsCOMPtr<nsIApplicationCache>     mApplicationCache;
 
   nsHttpRequestHead                 mRequestHead;
   nsCOMPtr<nsIInputStream>          mUploadStream;
+  nsCOMPtr<nsIRunnable>             mUploadCloneableCallback;
   nsAutoPtr<nsHttpResponseHead>     mResponseHead;
   nsRefPtr<nsHttpConnectionInfo>    mConnectionInfo;
   nsCOMPtr<nsIProxyInfo>            mProxyInfo;
   nsCOMPtr<nsISupports>             mSecurityInfo;
 
   nsCString                         mSpec; // ASCII encoded URL spec
   nsCString                         mContentTypeHint;
   nsCString                         mContentCharsetHint;
--- a/netwerk/protocol/http/HttpChannelChild.cpp
+++ b/netwerk/protocol/http/HttpChannelChild.cpp
@@ -2265,18 +2265,17 @@ HttpChannelChild::OverrideWithSynthesize
   // however, we want to respect the encoding of the final result instead.
   if (!WillRedirect(aResponseHead)) {
     SetApplyConversion(false);
   }
 
   mResponseHead = aResponseHead;
   mSynthesizedResponse = true;
 
-  uint16_t status = mResponseHead->Status();
-  if (status != 200 && status != 404) {
+  if (WillRedirect(mResponseHead)) {
     // Continue with the original cross-process request
     nsresult rv = ContinueAsyncOpen();
     NS_ENSURE_SUCCESS_VOID(rv);
     return;
   }
 
   // In our current implementation, the FetchEvent handler will copy the
   // response stream completely into the pipe backing the input stream so we
--- a/netwerk/protocol/http/nsCORSListenerProxy.cpp
+++ b/netwerk/protocol/http/nsCORSListenerProxy.cpp
@@ -511,18 +511,20 @@ nsCORSListenerProxy::OnStartRequest(nsIR
           // OK to use mRequestingPrincipal since preflights never get
           // redirected.
           sPreflightCache->RemoveEntries(uri, mRequestingPrincipal);
         } else {
           nsCOMPtr<nsIHttpChannelChild> httpChannelChild =
             do_QueryInterface(channel);
           if (httpChannelChild) {
             rv = httpChannelChild->RemoveCorsPreflightCacheEntry(uri, mRequestingPrincipal);
-            if (NS_WARN_IF(NS_FAILED(rv))) {
-              return rv;
+            if (NS_FAILED(rv)) {
+              // Only warn here to ensure we fall through the request Cancel()
+              // and outer listener OnStartRequest() calls.
+              NS_WARNING("Failed to remove CORS preflight cache entry!");
             }
           }
         }
       }
     }
 
     aRequest->Cancel(NS_ERROR_DOM_BAD_URI);
     mOuterListener->OnStartRequest(aRequest, aContext);
--- a/testing/mozharness/configs/builds/build_pool_specifics.py
+++ b/testing/mozharness/configs/builds/build_pool_specifics.py
@@ -33,14 +33,18 @@ config = {
         'symbol_server_host': "symbolpush.mozilla.org",
         'stage_server': 'stage.mozilla.org',
         "sendchange_masters": ["buildbot-master81.build.mozilla.org:9301"],
         'taskcluster_index': 'index',
     },
     "taskcluster": {
         'graph_server': 'graphs.mozilla.org',
         'symbol_server_host': "symbolpush.mozilla.org",
-        'stage_server': 'stage.mozilla.org',
+        'stage_server': 'ignored',
         # use the relengapi proxy to talk to tooltool
         "tooltool_servers": ['http://relengapi/tooltool/'],
         "tooltool_url": 'http://relengapi/tooltool/',
+        'upload_env': {
+            'UPLOAD_HOST': 'localhost',
+            'UPLOAD_PATH': '/home/worker/artifacts',
+        },
     },
 }
--- a/testing/mozharness/mozharness/mozilla/building/buildbase.py
+++ b/testing/mozharness/mozharness/mozilla/building/buildbase.py
@@ -821,25 +821,28 @@ or run without that action (ie: --no-{ac
 
     def query_mach_build_env(self, multiLocale=None):
         c = self.config
         if multiLocale is None and self.query_is_nightly():
             multiLocale = c.get('multi_locale', False)
         mach_env = {}
         if c.get('upload_env'):
             mach_env.update(c['upload_env'])
-            mach_env['UPLOAD_HOST'] = mach_env['UPLOAD_HOST'] % {
-                'stage_server': c['stage_server']
-            }
-            mach_env['UPLOAD_USER'] = mach_env['UPLOAD_USER'] % {
-                'stage_username': c['stage_username']
-            }
-            mach_env['UPLOAD_SSH_KEY'] = mach_env['UPLOAD_SSH_KEY'] % {
-                'stage_ssh_key': c['stage_ssh_key']
-            }
+            if 'UPLOAD_HOST' in mach_env:
+                mach_env['UPLOAD_HOST'] = mach_env['UPLOAD_HOST'] % {
+                    'stage_server': c['stage_server']
+                }
+            if 'UPLOAD_USER' in mach_env:
+                mach_env['UPLOAD_USER'] = mach_env['UPLOAD_USER'] % {
+                    'stage_username': c['stage_username']
+                }
+            if 'UPLOAD_SSH_KEY' in mach_env:
+                mach_env['UPLOAD_SSH_KEY'] = mach_env['UPLOAD_SSH_KEY'] % {
+                    'stage_ssh_key': c['stage_ssh_key']
+                }
 
         if self.query_is_nightly():
             mach_env['LATEST_MAR_DIR'] = c['latest_mar_dir'] % {
                 'branch': self.branch
             }
 
         # _query_post_upload_cmd returns a list (a cmd list), for env sake here
         # let's make it a string
--- a/testing/taskcluster/scripts/builder/build-linux.sh
+++ b/testing/taskcluster/scripts/builder/build-linux.sh
@@ -20,35 +20,27 @@ echo "running as" $(id)
 : NEED_XVFB                     ${NEED_XVFB:=false}
 
 : MH_CUSTOM_BUILD_VARIANT_CFG   ${MH_CUSTOM_BUILD_VARIANT_CFG}
 : MH_BRANCH                     ${MH_BRANCH:=mozilla-central}
 : MH_BUILD_POOL                 ${MH_BUILD_POOL:=staging}
 
 : WORKSPACE                     ${WORKSPACE:=/home/worker/workspace}
 
-# files to be "uploaded" (moved to ~/artifacts) from obj-firefox/dist
-: DIST_UPLOADS                  ${DIST_UPLOADS:=""}
-# files which will be be prefixed with target before being sent to artifacts
-# e.g. DIST_TARGET_UPLOADS="a.zip" runs mv v2.0.a.zip mv artifacts/target.a.zip
-: DIST_TARGET_UPLOADS           ${DIST_TARGET_UPLOADS:=""}
-
 set -v
 
-# Don't run the upload step; this is passed through mozharness to mach.  Once
-# the mozharness scripts are not run in Buildbot anymore, this can be moved to
-# Mozharness (or the upload step removed from mach entirely)
-export MOZ_AUTOMATION_UPLOAD=0
-
 export MOZ_CRASHREPORTER_NO_REPORT=1
 export MOZ_OBJDIR=obj-firefox
 export MOZ_SYMBOLS_EXTRA_BUILDID=linux64
-export POST_SYMBOL_UPLOAD_CMD=/usr/local/bin/post-symbol-upload.py
 export TINDERBOX_OUTPUT=1
 
+# use "simple" package names so that they can be hard-coded in the task's
+# extras.locations
+export MOZ_SIMPLE_PACKAGE_NAME=target
+
 # Ensure that in tree libraries can be found
 export LIBRARY_PATH=$LIBRARY_PATH:$WORKSPACE/src/obj-firefox:$WORKSPACE/src/gcc/lib64
 
 # test required parameters are supplied
 if [[ -z ${MOZHARNESS_SCRIPT} ]]; then exit 1; fi
 if [[ -z ${MOZHARNESS_CONFIG} ]]; then exit 1; fi
 
 cleanup() {
@@ -131,25 +123,8 @@ python2.7 $WORKSPACE/build/src/testing/$
   --no-update \
   --no-upload-files \
   --no-sendchange \
   --log-level=debug \
   --work-dir=$WORKSPACE/build \
   --no-action=generate-build-stats \
   --branch=${MH_BRANCH} \
   --build-pool=${MH_BUILD_POOL}
-
-mkdir -p /home/worker/artifacts
-
-# upload auxiliary files
-cd $WORKSPACE/build/src/obj-firefox/dist
-
-for file in $DIST_UPLOADS
-do
-    mv $file $HOME/artifacts/$file
-done
-
-# Discard version numbers from packaged files, they just make it hard to write
-# the right filename in the task payload where artifacts are declared
-for file in $DIST_TARGET_UPLOADS
-do
-    mv *.$file $HOME/artifacts/target.$file
-done
--- a/testing/taskcluster/tasks/builds/linux64_clobber.yml
+++ b/testing/taskcluster/tasks/builds/linux64_clobber.yml
@@ -25,29 +25,27 @@ task:
     env:
       MOZHARNESS_SCRIPT: 'mozharness/scripts/fx_desktop_build.py'
       MOZHARNESS_CONFIG: 'builds/releng_base_linux_64_builds.py balrog/production.py'
       MH_BRANCH: {{project}}
       MH_BUILD_POOL: taskcluster
       # image paths
       TOOLTOOL_CACHE: '/home/worker/tooltool-cache'
       NEED_XVFB: true
-      DIST_UPLOADS: 'jsshell-linux-x86_64.zip'
-      DIST_TARGET_UPLOADS: 'x-test.linux-x86_64.tar.bz2 linux-x86_64.tar.bz2 linux-x86_64.json tests.zip crashreporter-symbols.zip'
 
     maxRunTime: 36000
 
     command: ["/bin/bash", "bin/build.sh"]
 
   extra:
     treeherderEnv:
       - production
       - staging
     treeherder:
       machine:
         # see https://github.com/mozilla/treeherder/blob/master/ui/js/values.js
         platform: linux64
     # Rather then enforcing particular conventions we require that all build
     # tasks provide the "build" extra field to specify where the build and tests
-    # files are located.
+    # files are located, relative to the task's artifacts URL
     locations:
-      build: 'public/build/target.linux-x86_64.tar.bz2'
+      build: 'public/build/target.tar.bz2'
       tests: 'public/build/target.tests.zip'
--- a/testing/taskcluster/tasks/builds/opt_macosx64.yml
+++ b/testing/taskcluster/tasks/builds/opt_macosx64.yml
@@ -29,23 +29,18 @@ task:
     features:
       relengAPIProxy: true
 
     env:
       MOZHARNESS_SCRIPT: 'mozharness/scripts/fx_desktop_build.py'
       MOZHARNESS_CONFIG: 'builds/releng_base_mac_64_cross_builds.py balrog/production.py'
       MH_BRANCH: {{project}}
       MH_BUILD_POOL: taskcluster
-      #TODO: bug 1164617 - remove Docker image hacks
-      LIBRARY_PATH: ""
-      CPLUS_INCLUDE_PATH: ""
       # image paths
       TOOLTOOL_CACHE: '/home/worker/tooltool-cache'
-      DIST_UPLOADS: 'jsshell-mac64.zip'
-      DIST_TARGET_UPLOADS: 'mac64.dmg mac64.json tests.zip crashreporter-symbols.zip'
 
     maxRunTime: 36000
 
     command: ["/bin/bash", "bin/build.sh"]
 
   extra:
     treeherderEnv:
       - production
@@ -53,10 +48,10 @@ task:
     treeherder:
       machine:
         # see https://github.com/mozilla/treeherder/blob/master/ui/js/values.js
         platform: osx-10-7
     # Rather then enforcing particular conventions we require that all build
     # tasks provide the "build" extra field to specify where the build and tests
     # files are located.
     locations:
-      build: 'public/build/target.mac64.dmg'
+      build: 'public/build/target.dmg'
       tests: 'public/build/target.tests.zip'
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/service-workers/cache-storage/window/__dir__.ini
@@ -0,0 +1,1 @@
+prefs: [dom.caches.enabled:true]
deleted file mode 100644
--- a/testing/web-platform/meta/service-workers/cache-storage/window/cache-add.https.html.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[cache-add.https.html]
-  type: testharness
-  prefs: [dom.caches.enabled:true]
deleted file mode 100644
--- a/testing/web-platform/meta/service-workers/cache-storage/window/cache-delete.https.html.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[cache-delete.https.html]
-  type: testharness
-  prefs: [dom.caches.enabled:true]
deleted file mode 100644
--- a/testing/web-platform/meta/service-workers/cache-storage/window/cache-storage-keys.https.html.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[cache-storage-keys.https.html]
-  type: testharness
-  prefs: [dom.caches.enabled:true]
deleted file mode 100644
--- a/testing/web-platform/meta/service-workers/cache-storage/window/cache-storage.https.html.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[cache-storage.https.html]
-  type: testharness
-  prefs: [dom.caches.enabled:true]
deleted file mode 100644
--- a/testing/web-platform/meta/service-workers/cache-storage/window/sandboxed-iframes.https.html.ini
+++ /dev/null
@@ -1,6 +0,0 @@
-[sandboxed-iframes.https.html]
-  type: testharness
-  prefs: [dom.caches.enabled:true]
-  [Sandboxed iframe without allow-same-origin is denied access]
-    expected: FAIL
-
--- a/testing/web-platform/tests/service-workers/cache-storage/resources/iframe.html
+++ b/testing/web-platform/tests/service-workers/cache-storage/resources/iframe.html
@@ -1,13 +1,18 @@
 <!DOCTYPE html>
 <title>ok</title>
 <script>
 window.onmessage = function(e) {
     var id = e.data.id;
     try {
-        self.caches;
-        window.parent.postMessage({id: id, result: 'allowed'}, '*');
+        var name = 'checkallowed';
+        self.caches.open(name).then(function (cache) {
+            self.caches.delete(name);
+            window.parent.postMessage({id: id, result: 'allowed'}, '*');
+        }).catch(function(e) {
+            window.parent.postMessage({id: id, result: 'denied', name: e.name, message: e.message}, '*');
+        });
     } catch (e) {
-        window.parent.postMessage({id: id, result: 'denied', name: e.name, message: e.message}, '*');
+        window.parent.postMessage({id: id, result: 'unexpecteddenied', name: e.name, message: e.message}, '*');
     }
 };
 </script>
--- a/toolkit/mozapps/update/common/updatedefines.h
+++ b/toolkit/mozapps/update/common/updatedefines.h
@@ -24,26 +24,32 @@
 #if defined(XP_WIN)
 # include <windows.h>
 # include <shlwapi.h>
 # include <direct.h>
 # include <io.h>
 # include <stdio.h>
 # include <stdarg.h>
 
-# define F_OK 00
-# define W_OK 02
-# define R_OK 04
+# ifndef F_OK
+#   define F_OK 00
+# endif
+# ifndef W_OK
+#   define W_OK 02
+# endif
+# ifndef R_OK
+#   define R_OK 04
+# endif
 # define S_ISDIR(s) (((s) & _S_IFMT) == _S_IFDIR)
 # define S_ISREG(s) (((s) & _S_IFMT) == _S_IFREG)
 
 # define access _access
 
 # define putenv _putenv
-# if _MSC_VER < 1900
+# if defined(_MSC_VER) && _MSC_VER < 1900
 #  define stat _stat
 # endif
 # define DELETE_DIR L"tobedeleted"
 # define CALLBACK_BACKUP_EXT L".moz-callback"
 
 # define LOG_S "%S"
 # define NS_T(str) L ## str
 # define NS_SLASH NS_T('\\')
--- a/toolkit/mozapps/update/tests/TestAUSHelper.cpp
+++ b/toolkit/mozapps/update/tests/TestAUSHelper.cpp
@@ -6,20 +6,26 @@
 # include <windows.h>
 # include <wintrust.h>
 # include <tlhelp32.h>
 # include <softpub.h>
 # include <direct.h>
 # include <io.h>
   typedef WCHAR NS_tchar;
 # define NS_main wmain
-# define F_OK 00
-# define W_OK 02
-# define R_OK 04
-# if _MSC_VER < 1900
+# ifndef F_OK
+#   define F_OK 00
+# endif
+# ifndef W_OK
+#   define W_OK 02
+# endif
+# ifndef R_OK
+#   define R_OK 04
+# endif
+# if defined(_MSC_VER) && _MSC_VER < 1900
 #  define stat _stat
 # endif
 # define NS_T(str) L ## str
 # define NS_tsnprintf(dest, count, fmt, ...) \
   { \
     int _count = count - 1; \
     _snwprintf(dest, _count, fmt, ##__VA_ARGS__); \
     dest[_count] = L'\0'; \
--- a/widget/cocoa/nsNativeThemeCocoa.h
+++ b/widget/cocoa/nsNativeThemeCocoa.h
@@ -119,17 +119,17 @@ protected:
                            mozilla::EventStates inState, nsIFrame* aFrame);
   void DrawSearchField(CGContextRef cgContext, const HIRect& inBoxRect,
                        nsIFrame* aFrame, mozilla::EventStates inState);
   void DrawPushButton(CGContextRef cgContext, const HIRect& inBoxRect,
                       mozilla::EventStates inState, uint8_t aWidgetType,
                       nsIFrame* aFrame);
   void DrawMenuIcon(CGContextRef cgContext, const CGRect& aRect,
                     mozilla::EventStates inState, nsIFrame* aFrame,
-                    const NSSize& aIconSize, const NSString* aImageName,
+                    const NSSize& aIconSize, NSString* aImageName,
                     bool aCenterHorizontally);
   void DrawButton(CGContextRef context, ThemeButtonKind inKind,
                   const HIRect& inBoxRect, bool inIsDefault, 
                   ThemeButtonValue inValue, ThemeButtonAdornment inAdornment,
                   mozilla::EventStates inState, nsIFrame* aFrame);
   void DrawFocusOutline(CGContextRef cgContext, const HIRect& inBoxRect,
                         mozilla::EventStates inState, uint8_t aWidgetType,
                         nsIFrame* aFrame);
--- a/widget/cocoa/nsNativeThemeCocoa.mm
+++ b/widget/cocoa/nsNativeThemeCocoa.mm
@@ -1108,27 +1108,27 @@ nsNativeThemeCocoa::DrawSearchField(CGCo
 
   NS_OBJC_END_TRY_ABORT_BLOCK;
 }
 
 static const NSSize kCheckmarkSize = NSMakeSize(11, 11);
 static const NSSize kMenuarrowSize = nsCocoaFeatures::OnLionOrLater() ?
                                      NSMakeSize(9, 10) : NSMakeSize(8, 10);
 static const NSSize kMenuScrollArrowSize = NSMakeSize(10, 8);
-static const NSString* kCheckmarkImage = @"image.MenuOnState";
-static const NSString* kMenuarrowRightImage = @"image.MenuSubmenu";
-static const NSString* kMenuarrowLeftImage = @"image.MenuSubmenuLeft";
-static const NSString* kMenuDownScrollArrowImage = @"image.MenuScrollDown";
-static const NSString* kMenuUpScrollArrowImage = @"image.MenuScrollUp";
+static NSString* kCheckmarkImage = @"MenuOnState";
+static NSString* kMenuarrowRightImage = @"MenuSubmenu";
+static NSString* kMenuarrowLeftImage = @"MenuSubmenuLeft";
+static NSString* kMenuDownScrollArrowImage = @"MenuScrollDown";
+static NSString* kMenuUpScrollArrowImage = @"MenuScrollUp";
 static const CGFloat kMenuIconIndent = 6.0f;
 
 void
 nsNativeThemeCocoa::DrawMenuIcon(CGContextRef cgContext, const CGRect& aRect,
                                  EventStates inState, nsIFrame* aFrame,
-                                 const NSSize& aIconSize, const NSString* aImageName,
+                                 const NSSize& aIconSize, NSString* aImageName,
                                  bool aCenterHorizontally)
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
 
   // Adjust size and position of our drawRect.
   CGFloat paddingX = std::max(CGFloat(0.0), aRect.size.width - aIconSize.width);
   CGFloat paddingY = std::max(CGFloat(0.0), aRect.size.height - aIconSize.height);
   CGFloat paddingStartX = std::min(paddingX, kMenuIconIndent);
@@ -1148,20 +1148,26 @@ nsNativeThemeCocoa::DrawMenuIcon(CGConte
   BOOL otherKeysAndValues = !nsCocoaFeatures::IsAtLeastVersion(10,7,5);
 
   // 2 states combined with 2 different backgroundTypeKeys on earlier versions.
   NSString* state = isDisabled ? @"disabled" :
     (isActive && !otherKeysAndValues) ? @"pressed" : @"normal";
   NSString* backgroundTypeKey = !otherKeysAndValues ? @"kCUIBackgroundTypeMenu" :
     !isDisabled && isActive ? @"backgroundTypeDark" : @"backgroundTypeLight";
 
+  NSString* imageName = aImageName;
+  if (!nsCocoaFeatures::OnElCapitanOrLater()) {
+    // Pre-10.11, image names are prefixed with "image."
+    imageName = [@"image." stringByAppendingString:aImageName];
+  }
+
   NSMutableArray* keys = [NSMutableArray arrayWithObjects:@"backgroundTypeKey",
     @"imageNameKey", @"state", @"widget", @"is.flipped", nil];
   NSMutableArray* values = [NSMutableArray arrayWithObjects: backgroundTypeKey,
-    aImageName, state, @"image", [NSNumber numberWithBool:YES], nil];
+    imageName, state, @"image", [NSNumber numberWithBool:YES], nil];
 
   if (otherKeysAndValues) { // Earlier versions used one more key-value pair.
     [keys insertObject:@"imageIsGrayscaleKey" atIndex:1];
     [values insertObject:[NSNumber numberWithBool:YES] atIndex:1];
   }
 
   RenderWithCoreUI(drawRect, cgContext,
                   [NSDictionary dictionaryWithObjects:values
--- a/xpcom/components/nsComponentManager.h
+++ b/xpcom/components/nsComponentManager.h
@@ -10,16 +10,17 @@
 #include "nsXPCOM.h"
 
 #include "xpcom-private.h"
 #include "nsIComponentManager.h"
 #include "nsIComponentRegistrar.h"
 #include "nsIMemoryReporter.h"
 #include "nsIServiceManager.h"
 #include "nsIFile.h"
+#include "mozilla/Atomics.h"
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/Module.h"
 #include "mozilla/ModuleLoader.h"
 #include "mozilla/Mutex.h"
 #include "nsXULAppAPI.h"
 #include "nsNativeModuleLoader.h"
 #include "nsIFactory.h"
 #include "nsIInterfaceRequestor.h"
@@ -119,17 +120,17 @@ public:
     // This method is a release-mode check
     if (PR_GetCurrentThread() == mOwnerThread) {
       MOZ_CRASH();
     }
   }
 
 private:
   mozilla::Mutex mMutex;
-  volatile PRThread* mOwnerThread;
+  mozilla::Atomic<PRThread*, mozilla::Relaxed> mOwnerThread;
 };
 
 typedef mozilla::BaseAutoLock<SafeMutex> SafeMutexAutoLock;
 typedef mozilla::BaseAutoUnlock<SafeMutex> SafeMutexAutoUnlock;
 
 class nsComponentManagerImpl final
   : public nsIComponentManager
   , public nsIServiceManager
--- a/xpcom/io/nsStorageStream.cpp
+++ b/xpcom/io/nsStorageStream.cpp
@@ -455,17 +455,25 @@ nsStorageInputStream::ReadSegments(nsWri
   while (remainingCapacity) {
     availableInSegment = mSegmentEnd - mReadCursor;
     if (!availableInSegment) {
       uint32_t available = mStorageStream->mLogicalLength - mLogicalCursor;
       if (!available) {
         goto out;
       }
 
-      mSegmentNum++;
+      // We have data in the stream, but if mSegmentEnd is zero, then we
+      // were likely constructed prior to any data being written into
+      // the stream.  Therefore, if mSegmentEnd is non-zero, we should
+      // move into the next segment; otherwise, we should stay in this
+      // segment so our input state can be updated and we can properly
+      // perform the initial read.
+      if (mSegmentEnd > 0) {
+        mSegmentNum++;
+      }
       mReadCursor = 0;
       mSegmentEnd = XPCOM_MIN(mSegmentSize, available);
       availableInSegment = mSegmentEnd;
     }
     const char* cur = mStorageStream->mSegmentedBuffer->GetSegment(mSegmentNum);
 
     count = XPCOM_MIN(availableInSegment, remainingCapacity);
     rv = aWriter(this, aClosure, cur + mReadCursor, aCount - remainingCapacity,
--- a/xpcom/io/nsStreamUtils.cpp
+++ b/xpcom/io/nsStreamUtils.cpp
@@ -852,16 +852,27 @@ NS_FillArray(FallibleTArray<char>& aDest
   // SetLengthAndRetainStorage here, see nsTArrayElementTraits::Construct()
   // in nsTArray.h:
   aDest.SetLengthAndRetainStorage(aKeep + *aNewBytes);
 
   MOZ_ASSERT(aDest.Length() <= aDest.Capacity(), "buffer overflow");
   return rv;
 }
 
+bool
+NS_InputStreamIsCloneable(nsIInputStream* aSource)
+{
+  if (!aSource) {
+    return false;
+  }
+
+  nsCOMPtr<nsICloneableInputStream> cloneable = do_QueryInterface(aSource);
+  return cloneable && cloneable->GetCloneable();
+}
+
 nsresult
 NS_CloneInputStream(nsIInputStream* aSource, nsIInputStream** aCloneOut,
                     nsIInputStream** aReplacementOut)
 {
   if (NS_WARN_IF(!aSource)) {
     return NS_ERROR_FAILURE;
   }
 
--- a/xpcom/io/nsStreamUtils.h
+++ b/xpcom/io/nsStreamUtils.h
@@ -260,16 +260,22 @@ struct MOZ_STACK_CLASS nsWriteSegmentThu
  *        failed
  * @return the result from aInput->Read(...)
  */
 extern NS_METHOD
 NS_FillArray(FallibleTArray<char>& aDest, nsIInputStream* aInput,
              uint32_t aKeep, uint32_t* aNewBytes);
 
 /**
+ * Return true if the given stream can be directly cloned.
+ */
+extern bool
+NS_InputStreamIsCloneable(nsIInputStream* aSource);
+
+/**
  * Clone the provided source stream in the most efficient way possible.  This
  * first attempts to QI to nsICloneableInputStream to use Clone().  If that is
  * not supported or its cloneable attribute is false, then a fallback clone is
  * provided by copying the source to a pipe.  In this case the caller must
  * replace the source stream with the resulting replacement stream.  The clone
  * and the replacement stream are then cloneable using nsICloneableInputStream
  * without duplicating memory.  This fallback clone using the pipe is only
  * performed if a replacement stream parameter is also passed in.
--- a/xpcom/tests/gtest/TestStorageStream.cpp
+++ b/xpcom/tests/gtest/TestStorageStream.cpp
@@ -9,27 +9,29 @@
 #include "Helpers.h"
 #include "nsCOMPtr.h"
 #include "nsICloneableInputStream.h"
 #include "nsIInputStream.h"
 #include "nsIOutputStream.h"
 #include "nsIStorageStream.h"
 
 namespace {
+
 void
 WriteData(nsIOutputStream* aOut, nsTArray<char>& aData, uint32_t aNumBytes,
           nsACString& aDataWritten)
 {
   uint32_t n;
   nsresult rv = aOut->Write(aData.Elements(), aNumBytes, &n);
   EXPECT_TRUE(NS_SUCCEEDED(rv));
   aDataWritten.Append(aData.Elements(), aNumBytes);
 }
 
 } // namespace
+
 TEST(StorageStreams, Main)
 {
   // generate some test data we will write in 4k chunks to the stream
   nsTArray<char> kData;
   testing::CreateData(4096, kData);
 
   // track how much data was written so we can compare at the end
   nsAutoCString dataWritten;
@@ -84,8 +86,45 @@ TEST(StorageStreams, Main)
 
   // now, read all
   rv = stor->NewInputStream(0, getter_AddRefs(in));
   EXPECT_TRUE(NS_SUCCEEDED(rv));
 
   testing::ConsumeAndValidateStream(in, dataWritten);
   in = nullptr;
 }
+
+TEST(StorageStreams, EarlyInputStream)
+{
+  // generate some test data we will write in 4k chunks to the stream
+  nsTArray<char> kData;
+  testing::CreateData(4096, kData);
+
+  // track how much data was written so we can compare at the end
+  nsAutoCString dataWritten;
+
+  nsresult rv;
+  nsCOMPtr<nsIStorageStream> stor;
+
+  rv = NS_NewStorageStream(kData.Length(), UINT32_MAX, getter_AddRefs(stor));
+  EXPECT_TRUE(NS_SUCCEEDED(rv));
+
+  // Get input stream before writing data into the output stream
+  nsCOMPtr<nsIInputStream> in;
+  rv = stor->NewInputStream(0, getter_AddRefs(in));
+  EXPECT_TRUE(NS_SUCCEEDED(rv));
+
+  // Write data to output stream
+  nsCOMPtr<nsIOutputStream> out;
+  rv = stor->GetOutputStream(0, getter_AddRefs(out));
+  EXPECT_TRUE(NS_SUCCEEDED(rv));
+
+  WriteData(out, kData, kData.Length(), dataWritten);
+  WriteData(out, kData, kData.Length(), dataWritten);
+
+  rv = out->Close();
+  EXPECT_TRUE(NS_SUCCEEDED(rv));
+  out = nullptr;
+
+  // Should be able to consume input stream
+  testing::ConsumeAndValidateStream(in, dataWritten);
+  in = nullptr;
+}