Bug 785333 - Add ContainerLayer::RepositionChild. r=bas
authorChris Lord <chrislord.net@gmail.com>
Wed, 29 Aug 2012 11:52:55 +0100
changeset 105788 a9023cfa7721525a4646eab737d228dbafdf527c
parent 105787 c06b09e067d7e50f36ac41905b3fa52d2c8915c2
child 105789 2466826796a95cc6ca0a4e07e6b4d8bd92cc8c58
push id55
push usershu@rfrn.org
push dateThu, 30 Aug 2012 01:33:09 +0000
reviewersbas
bugs785333
milestone18.0a1
Bug 785333 - Add ContainerLayer::RepositionChild. r=bas Add a function that can be used to quickly reposition a layer child, rather than forcing removal/insertion and the extra work that can involve.
gfx/layers/Layers.h
gfx/layers/basic/BasicContainerLayer.cpp
gfx/layers/basic/BasicContainerLayer.h
gfx/layers/d3d10/ContainerLayerD3D10.cpp
gfx/layers/d3d10/ContainerLayerD3D10.h
gfx/layers/d3d10/LayerManagerD3D10.cpp
gfx/layers/d3d10/LayerManagerD3D10.h
gfx/layers/d3d9/ContainerLayerD3D9.cpp
gfx/layers/d3d9/ContainerLayerD3D9.h
gfx/layers/ipc/PLayers.ipdl
gfx/layers/ipc/ShadowLayers.cpp
gfx/layers/ipc/ShadowLayers.h
gfx/layers/ipc/ShadowLayersParent.cpp
gfx/layers/opengl/ContainerLayerOGL.cpp
gfx/layers/opengl/ContainerLayerOGL.h
--- a/gfx/layers/Layers.h
+++ b/gfx/layers/Layers.h
@@ -1156,16 +1156,24 @@ public:
    */
   virtual void InsertAfter(Layer* aChild, Layer* aAfter) = 0;
   /**
    * CONSTRUCTION PHASE ONLY
    * Remove aChild from the child list of this container. aChild must
    * be a child of this container.
    */
   virtual void RemoveChild(Layer* aChild) = 0;
+  /**
+   * CONSTRUCTION PHASE ONLY
+   * Reposition aChild from the child list of this container. aChild must
+   * be a child of this container.
+   * If aAfter is non-null, it must be a child of this container and we
+   * reposition after that layer. If it's null, we reposition at the start.
+   */
+  virtual void RepositionChild(Layer* aChild, Layer* aAfter) = 0;
 
   /**
    * CONSTRUCTION PHASE ONLY
    * Set the (sub)document metrics used to render the Layer subtree
    * rooted at this.
    */
   void SetFrameMetrics(const FrameMetrics& aFrameMetrics)
   {
@@ -1447,16 +1455,19 @@ class THEBES_API RefLayer : public Conta
 
 private:
   virtual void InsertAfter(Layer* aChild, Layer* aAfter)
   { MOZ_NOT_REACHED("no"); }
 
   virtual void RemoveChild(Layer* aChild)
   { MOZ_NOT_REACHED("no"); }
 
+  virtual void RepositionChild(Layer* aChild, Layer* aAfter)
+  { MOZ_NOT_REACHED("no"); }
+
   using ContainerLayer::SetFrameMetrics;
 
 public:
   /**
    * CONSTRUCTION PHASE ONLY
    * Set the ID of the layer's referent.
    */
   void SetReferentId(uint64_t aId)
--- a/gfx/layers/basic/BasicContainerLayer.cpp
+++ b/gfx/layers/basic/BasicContainerLayer.cpp
@@ -72,16 +72,17 @@ public:
   }
   virtual ~BasicShadowableContainerLayer()
   {
     MOZ_COUNT_DTOR(BasicShadowableContainerLayer);
   }
 
   virtual void InsertAfter(Layer* aChild, Layer* aAfter);
   virtual void RemoveChild(Layer* aChild);
+  virtual void RepositionChild(Layer* aChild, Layer* aAfter);
 
   virtual Layer* AsLayer() { return this; }
   virtual ShadowableLayer* AsShadowableLayer() { return this; }
 
   virtual void Disconnect()
   {
     BasicShadowableLayer::Disconnect();
   }
@@ -112,22 +113,38 @@ BasicShadowableContainerLayer::RemoveChi
 {
   if (HasShadow() && ShouldShadow(aChild)) {
     ShadowManager()->RemoveChild(ShadowManager()->Hold(this),
                                  ShadowManager()->Hold(aChild));
   }
   BasicContainerLayer::RemoveChild(aChild);
 }
 
+void
+BasicShadowableContainerLayer::RepositionChild(Layer* aChild, Layer* aAfter)
+{
+  if (HasShadow() && ShouldShadow(aChild)) {
+    while (aAfter && !ShouldShadow(aAfter)) {
+      aAfter = aAfter->GetPrevSibling();
+    }
+    ShadowManager()->RepositionChild(ShadowManager()->Hold(this),
+                                     ShadowManager()->Hold(aChild),
+                                     aAfter ? ShadowManager()->Hold(aAfter) : nullptr);
+  }
+  BasicContainerLayer::RepositionChild(aChild, aAfter);
+}
+
 class BasicShadowContainerLayer : public ShadowContainerLayer, public BasicImplData {
   template<class Container>
   friend void ContainerInsertAfter(Layer* aChild, Layer* aAfter, Container* aContainer);
   template<class Container>
   friend void ContainerRemoveChild(Layer* aChild, Container* aContainer);
   template<class Container>
+  friend void ContainerRepositionChild(Layer* aChild, Layer* aAfter, Container* aContainer);
+  template<class Container>
   friend void ContainerComputeEffectiveTransforms(const gfx3DMatrix& aTransformToSurface,
                                                   Container* aContainer);
 
 public:
   BasicShadowContainerLayer(BasicShadowLayerManager* aLayerManager) :
     ShadowContainerLayer(aLayerManager, static_cast<BasicImplData*>(this))
   {
     MOZ_COUNT_CTOR(BasicShadowContainerLayer);
@@ -140,16 +157,18 @@ public:
 
     MOZ_COUNT_DTOR(BasicShadowContainerLayer);
   }
 
   virtual void InsertAfter(Layer* aChild, Layer* aAfter)
   { ContainerInsertAfter(aChild, aAfter, this); }
   virtual void RemoveChild(Layer* aChild)
   { ContainerRemoveChild(aChild, this); }
+  virtual void RepositionChild(Layer* aChild, Layer* aAfter)
+  { ContainerRepositionChild(aChild, aAfter, this); }
 
   virtual void ComputeEffectiveTransforms(const gfx3DMatrix& aTransformToSurface)
   {
     ContainerComputeEffectiveTransforms(aTransformToSurface, this);
   }
 };
 
 class BasicShadowableRefLayer : public RefLayer, public BasicImplData,
--- a/gfx/layers/basic/BasicContainerLayer.h
+++ b/gfx/layers/basic/BasicContainerLayer.h
@@ -76,16 +76,61 @@ ContainerRemoveChild(Layer* aChild, Cont
   aChild->SetNextSibling(nullptr);
   aChild->SetPrevSibling(nullptr);
   aChild->SetParent(nullptr);
 
   aContainer->DidRemoveChild(aChild);
   NS_RELEASE(aChild);
 }
 
+template<class Container> void
+ContainerRepositionChild(Layer* aChild, Layer* aAfter, Container* aContainer)
+{
+  NS_ASSERTION(aChild->Manager() == aContainer->Manager(),
+               "Child has wrong manager");
+  NS_ASSERTION(aChild->GetParent() == aContainer,
+               "aChild not our child");
+  NS_ASSERTION(!aAfter ||
+               (aAfter->Manager() == aContainer->Manager() &&
+                aAfter->GetParent() == aContainer),
+               "aAfter is not our child");
+
+  Layer* prev = aChild->GetPrevSibling();
+  Layer* next = aChild->GetNextSibling();
+  if (prev == aAfter) {
+    // aChild is already in the correct position, nothing to do.
+    return;
+  }
+  if (prev) {
+    prev->SetNextSibling(next);
+  }
+  if (next) {
+    next->SetPrevSibling(prev);
+  }
+  if (!aAfter) {
+    aChild->SetPrevSibling(nullptr);
+    aChild->SetNextSibling(aContainer->mFirstChild);
+    if (aContainer->mFirstChild) {
+      aContainer->mFirstChild->SetPrevSibling(aChild);
+    }
+    aContainer->mFirstChild = aChild;
+    return;
+  }
+
+  Layer* afterNext = aAfter->GetNextSibling();
+  if (afterNext) {
+    afterNext->SetPrevSibling(aChild);
+  } else {
+    aContainer->mLastChild = aChild;
+  }
+  aAfter->SetNextSibling(aChild);
+  aChild->SetPrevSibling(aAfter);
+  aChild->SetNextSibling(afterNext);
+}
+
 template<class Container>
 static void
 ContainerComputeEffectiveTransforms(const gfx3DMatrix& aTransformToSurface,
                                     Container* aContainer)
 {
   // We push groups for container layers if we need to, which always
   // are aligned in device space, so it doesn't really matter how we snap
   // containers.
@@ -121,16 +166,18 @@ ContainerComputeEffectiveTransforms(cons
 }
 
 class BasicContainerLayer : public ContainerLayer, public BasicImplData {
   template<class Container>
   friend void ContainerInsertAfter(Layer* aChild, Layer* aAfter, Container* aContainer);
   template<class Container>
   friend void ContainerRemoveChild(Layer* aChild, Container* aContainer);
   template<class Container>
+  friend void ContainerRepositionChild(Layer* aChild, Layer* aAfter, Container* aContainer);
+  template<class Container>
   friend void ContainerComputeEffectiveTransforms(const gfx3DMatrix& aTransformToSurface,
                                                   Container* aContainer);
 
 public:
   BasicContainerLayer(BasicLayerManager* aManager) :
     ContainerLayer(aManager, static_cast<BasicImplData*>(this))
   {
     MOZ_COUNT_CTOR(BasicContainerLayer);
@@ -153,16 +200,23 @@ public:
 
   virtual void RemoveChild(Layer* aChild)
   { 
     NS_ASSERTION(BasicManager()->InConstruction(),
                  "Can only set properties in construction phase");
     ContainerRemoveChild(aChild, this);
   }
 
+  virtual void RepositionChild(Layer* aChild, Layer* aAfter)
+  {
+    NS_ASSERTION(BasicManager()->InConstruction(),
+                 "Can only set properties in construction phase");
+    ContainerRepositionChild(aChild, aAfter, this);
+  }
+
   virtual void ComputeEffectiveTransforms(const gfx3DMatrix& aTransformToSurface)
   {
     ContainerComputeEffectiveTransforms(aTransformToSurface, this);
   }
 
   /**
    * Returns true when:
    * a) no (non-hidden) childrens' visible areas overlap in
--- a/gfx/layers/d3d10/ContainerLayerD3D10.cpp
+++ b/gfx/layers/d3d10/ContainerLayerD3D10.cpp
@@ -94,28 +94,80 @@ ContainerRemoveChild(Container* aContain
   aChild->SetNextSibling(nullptr);
   aChild->SetPrevSibling(nullptr);
   aChild->SetParent(nullptr);
 
   aContainer->DidRemoveChild(aChild);
   NS_RELEASE(aChild);
 }
 
+template<class Container>
+static void
+ContainerRepositionChild(Container* aContainer, Layer* aChild, Layer* aAfter)
+{
+  NS_ASSERTION(aChild->Manager() == aContainer->Manager(),
+               "Child has wrong manager");
+  NS_ASSERTION(aChild->GetParent() == aContainer,
+               "aChild not our child");
+  NS_ASSERTION(!aAfter ||
+               (aAfter->Manager() == aContainer->Manager() &&
+                aAfter->GetParent() == aContainer),
+               "aAfter is not our child");
+
+  Layer* prev = aChild->GetPrevSibling();
+  Layer* next = aChild->GetNextSibling();
+  if (prev == aAfter) {
+    // aChild is already in the correct position, nothing to do.
+    return;
+  }
+  if (prev) {
+    prev->SetNextSibling(next);
+  }
+  if (next) {
+    next->SetPrevSibling(prev);
+  }
+  if (!aAfter) {
+    aChild->SetPrevSibling(nullptr);
+    aChild->SetNextSibling(aContainer->mFirstChild);
+    if (aContainer->mFirstChild) {
+      aContainer->mFirstChild->SetPrevSibling(aChild);
+    }
+    aContainer->mFirstChild = aChild;
+    return;
+  }
+
+  Layer* afterNext = aAfter->GetNextSibling();
+  if (afterNext) {
+    afterNext->SetPrevSibling(aChild);
+  } else {
+    aContainer->mLastChild = aChild;
+  }
+  aAfter->SetNextSibling(aChild);
+  aChild->SetPrevSibling(aAfter);
+  aChild->SetNextSibling(afterNext);
+}
+
 void
 ContainerLayerD3D10::InsertAfter(Layer* aChild, Layer* aAfter)
 {
   ContainerInsertAfter(this, aChild, aAfter);
 }
 
 void
 ContainerLayerD3D10::RemoveChild(Layer *aChild)
 {
   ContainerRemoveChild(this, aChild);
 }
 
+void
+ContainerLayerD3D10::RepositionChild(Layer* aChild, Layer* aAfter)
+{
+  ContainerRepositionChild(this, aChild, aAfter);
+}
+
 Layer*
 ContainerLayerD3D10::GetLayer()
 {
   return this;
 }
 
 LayerD3D10*
 ContainerLayerD3D10::GetFirstChildD3D10()
@@ -388,16 +440,22 @@ ShadowContainerLayerD3D10::InsertAfter(L
 
 void
 ShadowContainerLayerD3D10::RemoveChild(Layer* aChild)
 {
   ContainerRemoveChild(this, aChild);
 }
 
 void
+ShadowContainerLayerD3D10::RepositionChild(Layer* aChild, Layer* aAfter)
+{
+  ContainerRepositionChild(this, aChild, aAfter);
+}
+
+void
 ShadowContainerLayerD3D10::ComputeEffectiveTransforms(const gfx3DMatrix& aTransformToSurface)
 {
   DefaultComputeEffectiveTransforms(aTransformToSurface);
 }
 
 LayerD3D10*
 ShadowContainerLayerD3D10::GetFirstChildD3D10()
 {
--- a/gfx/layers/d3d10/ContainerLayerD3D10.h
+++ b/gfx/layers/d3d10/ContainerLayerD3D10.h
@@ -10,35 +10,41 @@
 
 namespace mozilla {
 namespace layers {
 
 template<class Container>
 static void ContainerInsertAfter(Container* aContainer, Layer* aChild, Layer* aAfter);
 template<class Container>
 static void ContainerRemoveChild(Container* aContainer, Layer* aChild);
+template<class Container>
+static void ContainerRepositionChild(Container* aContainer, Layer* aChild, Layer* aAfter);
 
 class ContainerLayerD3D10 : public ContainerLayer,
                             public LayerD3D10
 {
   template<class Container>
   friend void ContainerInsertAfter(Container* aContainer, Layer* aChild, Layer* aAfter);
   template<class Container>
   friend void ContainerRemoveChild(Container* aContainer, Layer* aChild);
+  template<class Container>
+  friend void ContainerRepositionChild(Container* aContainer, Layer* aChild, Layer* aAfter);
 public:
   ContainerLayerD3D10(LayerManagerD3D10 *aManager);
   ~ContainerLayerD3D10();
 
   nsIntRect GetVisibleRect() { return mVisibleRegion.GetBounds(); }
 
   /* ContainerLayer implementation */
   virtual void InsertAfter(Layer* aChild, Layer* aAfter);
 
   virtual void RemoveChild(Layer* aChild);
 
+  virtual void RepositionChild(Layer* aChild, Layer* aAfter);
+
   /* LayerD3D10 implementation */
   virtual Layer* GetLayer();
 
   virtual LayerD3D10* GetFirstChildD3D10();
 
   virtual void RenderLayer();
   virtual void Validate();
 
@@ -55,24 +61,28 @@ public:
 // honor the transform/cliprect/etc. when rendering.
 class ShadowContainerLayerD3D10 : public ShadowContainerLayer,
                                   public LayerD3D10
 {
   template<class Container>
   friend void ContainerInsertAfter(Container* aContainer, Layer* aChild, Layer* aAfter);
   template<class Container>
   friend void ContainerRemoveChild(Container* aContainer, Layer* aChild);
+  template<class Container>
+  friend void ContainerRepositionChild(Container* aContainer, Layer* aChild, Layer* aAfter);
 public:
   ShadowContainerLayerD3D10(LayerManagerD3D10 *aManager);
   ~ShadowContainerLayerD3D10();
 
   void InsertAfter(Layer* aChild, Layer* aAfter);
 
   void RemoveChild(Layer* aChild);
 
+  void RepositionChild(Layer* aChild, Layer* aAfter);
+
   virtual void ComputeEffectiveTransforms(const gfx3DMatrix& aTransformToSurface);
 
   /* LayerD3D10 implementation */
   virtual LayerD3D10 *GetFirstChildD3D10();
   virtual Layer* GetLayer() { return this; }
   virtual void RenderLayer();
   virtual void Validate();
   virtual void LayerManagerDestroyed();
--- a/gfx/layers/d3d10/LayerManagerD3D10.cpp
+++ b/gfx/layers/d3d10/LayerManagerD3D10.cpp
@@ -988,11 +988,16 @@ DummyRoot::InsertAfter(Layer* aLayer, La
 
 void
 DummyRoot::RemoveChild(Layer* aNull)
 {
   NS_ABORT_IF_FALSE(!aNull, "Unused argument should be null");
   NS_IF_RELEASE(mFirstChild);
 }
 
+void
+DummyRoot::RepositionChild(Layer* aUnused1, Layer* aUnused2)
+{
+}
+
 
 }
 }
--- a/gfx/layers/d3d10/LayerManagerD3D10.h
+++ b/gfx/layers/d3d10/LayerManagerD3D10.h
@@ -352,16 +352,17 @@ public:
 class DummyRoot : public ContainerLayer, public ShadowableLayer {
 public:
   DummyRoot(LayerManagerD3D10* aManager);
   virtual ~DummyRoot();
 
   void ComputeEffectiveTransforms(const gfx3DMatrix&) {}
   void InsertAfter(Layer*, Layer*);
   void RemoveChild(Layer*);
+  void RepositionChild(Layer*, Layer*);
   Layer* AsLayer() { return this; }
 
   void SetShadow(PLayerChild* aChild) { mShadow = aChild; }
 };
 
 } /* layers */
 } /* mozilla */
 
--- a/gfx/layers/d3d9/ContainerLayerD3D9.cpp
+++ b/gfx/layers/d3d9/ContainerLayerD3D9.cpp
@@ -78,16 +78,62 @@ ContainerRemoveChild(Container* aContain
   aChild->SetNextSibling(nullptr);
   aChild->SetPrevSibling(nullptr);
   aChild->SetParent(nullptr);
 
   aContainer->DidRemoveChild(aChild);
   NS_RELEASE(aChild);
 }
 
+template<class Container>
+static void
+ContainerRepositionChild(Container* aContainer, Layer* aChild, Layer* aAfter)
+{
+  NS_ASSERTION(aChild->Manager() == aContainer->Manager(),
+               "Child has wrong manager");
+  NS_ASSERTION(aChild->GetParent() == aContainer,
+               "aChild not our child");
+  NS_ASSERTION(!aAfter ||
+               (aAfter->Manager() == aContainer->Manager() &&
+                aAfter->GetParent() == aContainer),
+               "aAfter is not our child");
+
+  Layer* prev = aChild->GetPrevSibling();
+  Layer* next = aChild->GetNextSibling();
+  if (prev == aAfter) {
+    // aChild is already in the correct position, nothing to do.
+    return;
+  }
+  if (prev) {
+    prev->SetNextSibling(next);
+  }
+  if (next) {
+    next->SetPrevSibling(prev);
+  }
+  if (!aAfter) {
+    aChild->SetPrevSibling(nullptr);
+    aChild->SetNextSibling(aContainer->mFirstChild);
+    if (aContainer->mFirstChild) {
+      aContainer->mFirstChild->SetPrevSibling(aChild);
+    }
+    aContainer->mFirstChild = aChild;
+    return;
+  }
+
+  Layer* afterNext = aAfter->GetNextSibling();
+  if (afterNext) {
+    afterNext->SetPrevSibling(aChild);
+  } else {
+    aContainer->mLastChild = aChild;
+  }
+  aAfter->SetNextSibling(aChild);
+  aChild->SetPrevSibling(aAfter);
+  aChild->SetNextSibling(afterNext);
+}
+
 static inline LayerD3D9*
 GetNextSibling(LayerD3D9* aLayer)
 {
    Layer* layer = aLayer->GetLayer()->GetNextSibling();
    return layer ? static_cast<LayerD3D9*>(layer->
                                          ImplData())
                  : nullptr;
 }
@@ -298,16 +344,22 @@ ContainerLayerD3D9::InsertAfter(Layer* a
 }
 
 void
 ContainerLayerD3D9::RemoveChild(Layer *aChild)
 {
   ContainerRemoveChild(this, aChild);
 }
 
+void
+ContainerLayerD3D9::RepositionChild(Layer* aChild, Layer* aAfter)
+{
+  ContainerRepositionChild(this, aChild, aAfter);
+}
+
 Layer*
 ContainerLayerD3D9::GetLayer()
 {
   return this;
 }
 
 LayerD3D9*
 ContainerLayerD3D9::GetFirstChildD3D9()
@@ -353,16 +405,22 @@ ShadowContainerLayerD3D9::InsertAfter(La
 
 void
 ShadowContainerLayerD3D9::RemoveChild(Layer *aChild)
 {
   ContainerRemoveChild(this, aChild);
 }
 
 void
+ShadowContainerLayerD3D9::RepositionChild(Layer* aChild, Layer* aAfter)
+{
+  ContainerRepositionChild(this, aChild, aAfter);
+}
+
+void
 ShadowContainerLayerD3D9::Destroy()
 {
   while (mFirstChild) {
     RemoveChild(mFirstChild);
   }
 }
 
 LayerD3D9*
--- a/gfx/layers/d3d9/ContainerLayerD3D9.h
+++ b/gfx/layers/d3d9/ContainerLayerD3D9.h
@@ -12,39 +12,45 @@
 namespace mozilla {
 namespace layers {
   
 template<class Container>
 static void ContainerInsertAfter(Container* aContainer, Layer* aChild, Layer* aAfter);
 template<class Container>
 static void ContainerRemoveChild(Container* aContainer, Layer* aChild);
 template<class Container>
+static void ContainerRepositionChild(Container* aContainer, Layer* aChild, Layer* aAfter);
+template<class Container>
 static void ContainerRender(Container* aContainer, LayerManagerD3D9* aManager);
 
 class ContainerLayerD3D9 : public ContainerLayer,
                            public LayerD3D9
 {
   template<class Container>
   friend void ContainerInsertAfter(Container* aContainer, Layer* aChild, Layer* aAfter);
   template<class Container>
   friend void ContainerRemoveChild(Container* aContainer, Layer* aChild);
   template<class Container>
+  friend void ContainerRepositionChild(Container* aContainer, Layer* aChild, Layer* aAfter);
+  template<class Container>
   friend void ContainerRender(Container* aContainer, LayerManagerD3D9* aManager);
 
 public:
   ContainerLayerD3D9(LayerManagerD3D9 *aManager);
   ~ContainerLayerD3D9();
 
   nsIntRect GetVisibleRect() { return mVisibleRegion.GetBounds(); }
 
   /* ContainerLayer implementation */
   virtual void InsertAfter(Layer* aChild, Layer* aAfter);
 
   virtual void RemoveChild(Layer* aChild);
 
+  virtual void RepositionChild(Layer* aChild, Layer* aAfter);
+
   /* LayerD3D9 implementation */
   Layer* GetLayer();
 
   LayerD3D9* GetFirstChildD3D9();
 
   bool IsEmpty();
 
   void RenderLayer();
@@ -60,26 +66,30 @@ public:
 class ShadowContainerLayerD3D9 : public ShadowContainerLayer,
                                 public LayerD3D9
 {
   template<class Container>
   friend void ContainerInsertAfter(Container* aContainer, Layer* aChild, Layer* aAfter);
   template<class Container>
   friend void ContainerRemoveChild(Container* aContainer, Layer* aChild);
   template<class Container>
+  friend void ContainerRepositionChild(Container* aContainer, Layer* aChild, Layer* aAfter);
+  template<class Container>
   friend void ContainerRender(Container* aContainer, LayerManagerD3D9* aManager);
 
 public:
   ShadowContainerLayerD3D9(LayerManagerD3D9 *aManager);
   ~ShadowContainerLayerD3D9();
 
   void InsertAfter(Layer* aChild, Layer* aAfter);
 
   void RemoveChild(Layer* aChild);
 
+  void RepositionChild(Layer* aChild, Layer* aAfter);
+
   // LayerD3D9 Implementation
   virtual Layer* GetLayer() { return this; }
 
   virtual void Destroy();
 
   LayerD3D9* GetFirstChildD3D9();
 
   virtual void RenderLayer();
--- a/gfx/layers/ipc/PLayers.ipdl
+++ b/gfx/layers/ipc/PLayers.ipdl
@@ -212,20 +212,22 @@ struct LayerAttributes {
 
 struct OpSetLayerAttributes {
   PLayer layer;
   LayerAttributes attrs;
 };
 
 
 // Monkey with the tree structure
-struct OpSetRoot      { PLayer root; };
-struct OpInsertAfter  { PLayer container; PLayer childLayer; PLayer after; };
-struct OpAppendChild  { PLayer container; PLayer childLayer; };
-struct OpRemoveChild  { PLayer container; PLayer childLayer; };
+struct OpSetRoot          { PLayer root; };
+struct OpInsertAfter      { PLayer container; PLayer childLayer; PLayer after; };
+struct OpAppendChild      { PLayer container; PLayer childLayer; };
+struct OpRemoveChild      { PLayer container; PLayer childLayer; };
+struct OpRepositionChild  { PLayer container; PLayer childLayer; PLayer after; };
+struct OpRaiseToTopChild  { PLayer container; PLayer childLayer; };
 
 
 // Paint (buffer update)
 struct OpPaintThebesBuffer {
   PLayer layer;
   ThebesBuffer newFrontBuffer;
   nsIntRegion updatedRegion;
 };
@@ -259,16 +261,18 @@ union Edit {
   OpCreateRefLayer;
 
   OpSetLayerAttributes;
 
   OpSetRoot;
   OpInsertAfter;
   OpAppendChild;
   OpRemoveChild;
+  OpRepositionChild;
+  OpRaiseToTopChild;
 
   OpPaintThebesBuffer;
   OpPaintTiledLayerBuffer;
   OpPaintCanvas;
   OpPaintImage;
 };
 
 
--- a/gfx/layers/ipc/ShadowLayers.cpp
+++ b/gfx/layers/ipc/ShadowLayers.cpp
@@ -214,16 +214,29 @@ ShadowLayerForwarder::InsertAfter(Shadow
 }
 void
 ShadowLayerForwarder::RemoveChild(ShadowableLayer* aContainer,
                                   ShadowableLayer* aChild)
 {
   mTxn->AddEdit(OpRemoveChild(NULL, Shadow(aContainer),
                               NULL, Shadow(aChild)));
 }
+void
+ShadowLayerForwarder::RepositionChild(ShadowableLayer* aContainer,
+                                      ShadowableLayer* aChild,
+                                      ShadowableLayer* aAfter)
+{
+  if (aAfter)
+    mTxn->AddEdit(OpRepositionChild(NULL, Shadow(aContainer),
+                                    NULL, Shadow(aChild),
+                                    NULL, Shadow(aAfter)));
+  else
+    mTxn->AddEdit(OpRaiseToTopChild(NULL, Shadow(aContainer),
+                                    NULL, Shadow(aChild)));
+}
 
 void
 ShadowLayerForwarder::PaintedThebesBuffer(ShadowableLayer* aThebes,
                                           const nsIntRegion& aUpdatedRegion,
                                           const nsIntRect& aBufferRect,
                                           const nsIntPoint& aBufferRotation,
                                           const SurfaceDescriptor& aNewFrontBuffer)
 {
--- a/gfx/layers/ipc/ShadowLayers.h
+++ b/gfx/layers/ipc/ShadowLayers.h
@@ -161,16 +161,19 @@ public:
    * NULL to indicated that |aChild| should be appended to the end of
    * |aContainer|'s child list.
    */
   void InsertAfter(ShadowableLayer* aContainer,
                    ShadowableLayer* aChild,
                    ShadowableLayer* aAfter=NULL);
   void RemoveChild(ShadowableLayer* aContainer,
                    ShadowableLayer* aChild);
+  void RepositionChild(ShadowableLayer* aContainer,
+                       ShadowableLayer* aChild,
+                       ShadowableLayer* aAfter=NULL);
 
   /**
    * Set aMaskLayer as the mask on aLayer.
    * Note that only image layers are properly supported
    * ShadowLayersParent::UpdateMask and accompanying ipdl
    * will need changing to update properties for other kinds
    * of mask layer.
    */
--- a/gfx/layers/ipc/ShadowLayersParent.cpp
+++ b/gfx/layers/ipc/ShadowLayersParent.cpp
@@ -83,16 +83,43 @@ ShadowContainer(const OpRemoveChild& op)
   return cast(op.containerParent());
 }
 static ShadowLayerParent*
 ShadowChild(const OpRemoveChild& op)
 {
   return cast(op.childLayerParent());
 }
 
+static ShadowLayerParent*
+ShadowContainer(const OpRepositionChild& op)
+{
+  return cast(op.containerParent());
+}
+static ShadowLayerParent*
+ShadowChild(const OpRepositionChild& op)
+{
+  return cast(op.childLayerParent());
+}
+static ShadowLayerParent*
+ShadowAfter(const OpRepositionChild& op)
+{
+  return cast(op.afterParent());
+}
+
+static ShadowLayerParent*
+ShadowContainer(const OpRaiseToTopChild& op)
+{
+  return cast(op.containerParent());
+}
+static ShadowLayerParent*
+ShadowChild(const OpRaiseToTopChild& op)
+{
+  return cast(op.childLayerParent());
+}
+
 //--------------------------------------------------
 // ShadowLayersParent
 ShadowLayersParent::ShadowLayersParent(ShadowLayerManager* aManager,
                                        ShadowLayersManager* aLayersManager,
                                        uint64_t aId)
   : mLayerManager(aManager)
   , mShadowLayersManager(aLayersManager)
   , mId(aId)
@@ -322,16 +349,32 @@ ShadowLayersParent::RecvUpdate(const Inf
     case Edit::TOpRemoveChild: {
       MOZ_LAYERS_LOG(("[ParentSide] RemoveChild"));
 
       const OpRemoveChild& orc = edit.get_OpRemoveChild();
       Layer* childLayer = ShadowChild(orc)->AsLayer();
       ShadowContainer(orc)->AsContainer()->RemoveChild(childLayer);
       break;
     }
+    case Edit::TOpRepositionChild: {
+      MOZ_LAYERS_LOG(("[ParentSide] RepositionChild"));
+
+      const OpRepositionChild& orc = edit.get_OpRepositionChild();
+      ShadowContainer(orc)->AsContainer()->RepositionChild(
+        ShadowChild(orc)->AsLayer(), ShadowAfter(orc)->AsLayer());
+      break;
+    }
+    case Edit::TOpRaiseToTopChild: {
+      MOZ_LAYERS_LOG(("[ParentSide] RaiseToTopChild"));
+
+      const OpRaiseToTopChild& rtc = edit.get_OpRaiseToTopChild();
+      ShadowContainer(rtc)->AsContainer()->RepositionChild(
+        ShadowChild(rtc)->AsLayer(), NULL);
+      break;
+    }
 
     case Edit::TOpPaintTiledLayerBuffer: {
       MOZ_LAYERS_LOG(("[ParentSide] Paint TiledLayerBuffer"));
       const OpPaintTiledLayerBuffer& op = edit.get_OpPaintTiledLayerBuffer();
       ShadowLayerParent* shadow = AsShadowLayer(op);
 
       ShadowThebesLayer* shadowLayer = static_cast<ShadowThebesLayer*>(shadow->AsLayer());
       TiledLayerComposer* tileComposer = shadowLayer->AsTiledLayerComposer();
--- a/gfx/layers/opengl/ContainerLayerOGL.cpp
+++ b/gfx/layers/opengl/ContainerLayerOGL.cpp
@@ -77,16 +77,62 @@ ContainerRemoveChild(Container* aContain
   aChild->SetParent(nullptr);
 
   aContainer->DidRemoveChild(aChild);
   NS_RELEASE(aChild);
 }
 
 template<class Container>
 static void
+ContainerRepositionChild(Container* aContainer, Layer* aChild, Layer* aAfter)
+{
+  NS_ASSERTION(aChild->Manager() == aContainer->Manager(),
+               "Child has wrong manager");
+  NS_ASSERTION(aChild->GetParent() == aContainer,
+               "aChild not our child");
+  NS_ASSERTION(!aAfter ||
+               (aAfter->Manager() == aContainer->Manager() &&
+                aAfter->GetParent() == aContainer),
+               "aAfter is not our child");
+
+  Layer* prev = aChild->GetPrevSibling();
+  Layer* next = aChild->GetNextSibling();
+  if (prev == aAfter) {
+    // aChild is already in the correct position, nothing to do.
+    return;
+  }
+  if (prev) {
+    prev->SetNextSibling(next);
+  }
+  if (next) {
+    next->SetPrevSibling(prev);
+  }
+  if (!aAfter) {
+    aChild->SetPrevSibling(nullptr);
+    aChild->SetNextSibling(aContainer->mFirstChild);
+    if (aContainer->mFirstChild) {
+      aContainer->mFirstChild->SetPrevSibling(aChild);
+    }
+    aContainer->mFirstChild = aChild;
+    return;
+  }
+
+  Layer* afterNext = aAfter->GetNextSibling();
+  if (afterNext) {
+    afterNext->SetPrevSibling(aChild);
+  } else {
+    aContainer->mLastChild = aChild;
+  }
+  aAfter->SetNextSibling(aChild);
+  aChild->SetPrevSibling(aAfter);
+  aChild->SetNextSibling(afterNext);
+}
+
+template<class Container>
+static void
 ContainerDestroy(Container* aContainer)
  {
   if (!aContainer->mDestroyed) {
     while (aContainer->mFirstChild) {
       aContainer->GetFirstChildOGL()->Destroy();
       aContainer->RemoveChild(aContainer->mFirstChild);
     }
     aContainer->mDestroyed = true;
@@ -299,16 +345,22 @@ ContainerLayerOGL::InsertAfter(Layer* aC
 
 void
 ContainerLayerOGL::RemoveChild(Layer *aChild)
 {
   ContainerRemoveChild(this, aChild);
 }
 
 void
+ContainerLayerOGL::RepositionChild(Layer* aChild, Layer* aAfter)
+{
+  ContainerRepositionChild(this, aChild, aAfter);
+}
+
+void
 ContainerLayerOGL::Destroy()
 {
   ContainerDestroy(this);
 }
 
 LayerOGL*
 ContainerLayerOGL::GetFirstChildOGL()
 {
@@ -362,16 +414,22 @@ ShadowContainerLayerOGL::InsertAfter(Lay
 
 void
 ShadowContainerLayerOGL::RemoveChild(Layer *aChild)
 {
   ContainerRemoveChild(this, aChild);
 }
 
 void
+ShadowContainerLayerOGL::RepositionChild(Layer* aChild, Layer* aAfter)
+{
+  ContainerRepositionChild(this, aChild, aAfter);
+}
+
+void
 ShadowContainerLayerOGL::Destroy()
 {
   ContainerDestroy(this);
 }
 
 LayerOGL*
 ShadowContainerLayerOGL::GetFirstChildOGL()
 {
--- a/gfx/layers/opengl/ContainerLayerOGL.h
+++ b/gfx/layers/opengl/ContainerLayerOGL.h
@@ -15,46 +15,52 @@
 namespace mozilla {
 namespace layers {
 
 template<class Container>
 static void ContainerInsertAfter(Container* aContainer, Layer* aChild, Layer* aAfter);
 template<class Container>
 static void ContainerRemoveChild(Container* aContainer, Layer* aChild);
 template<class Container>
+static void ContainerRepositionChild(Container* aContainer, Layer* aChild, Layer* aAfter);
+template<class Container>
 static void ContainerDestroy(Container* aContainer);
 template<class Container>
 static void ContainerRender(Container* aContainer,
                             int aPreviousFrameBuffer,
                             const nsIntPoint& aOffset,
                             LayerManagerOGL* aManager);
 
 class ContainerLayerOGL : public ContainerLayer,
                           public LayerOGL
 {
   template<class Container>
   friend void ContainerInsertAfter(Container* aContainer, Layer* aChild, Layer* aAfter);
   template<class Container>
   friend void ContainerRemoveChild(Container* aContainer, Layer* aChild);
   template<class Container>
+  friend void ContainerRepositionChild(Container* aContainer, Layer* aChild, Layer* aAfter);
+  template<class Container>
   friend void ContainerDestroy(Container* aContainer);
   template<class Container>
   friend void ContainerRender(Container* aContainer,
                               int aPreviousFrameBuffer,
                               const nsIntPoint& aOffset,
                               LayerManagerOGL* aManager);
 
 public:
   ContainerLayerOGL(LayerManagerOGL *aManager);
   ~ContainerLayerOGL();
 
   void InsertAfter(Layer* aChild, Layer* aAfter);
 
   void RemoveChild(Layer* aChild);
 
+  void RepositionChild(Layer* aChild, Layer* aAfter);
+
   /** LayerOGL implementation */
   Layer* GetLayer() { return this; }
 
   void Destroy();
 
   LayerOGL* GetFirstChildOGL();
 
   virtual void RenderLayer(int aPreviousFrameBuffer,
@@ -71,31 +77,35 @@ public:
 class ShadowContainerLayerOGL : public ShadowContainerLayer,
                                 public LayerOGL
 {
   template<class Container>
   friend void ContainerInsertAfter(Container* aContainer, Layer* aChild, Layer* aAfter);
   template<class Container>
   friend void ContainerRemoveChild(Container* aContainer, Layer* aChild);
   template<class Container>
+  friend void ContainerRepositionChild(Container* aContainer, Layer* aChild, Layer* aAfter);
+  template<class Container>
   friend void ContainerDestroy(Container* aContainer);
   template<class Container>
   friend void ContainerRender(Container* aContainer,
                               int aPreviousFrameBuffer,
                               const nsIntPoint& aOffset,
                               LayerManagerOGL* aManager);
 
 public:
   ShadowContainerLayerOGL(LayerManagerOGL *aManager);
   ~ShadowContainerLayerOGL();
 
   void InsertAfter(Layer* aChild, Layer* aAfter);
 
   void RemoveChild(Layer* aChild);
 
+  void RepositionChild(Layer* aChild, Layer* aAfter);
+
   // LayerOGL Implementation
   virtual Layer* GetLayer() { return this; }
 
   virtual void Destroy();
 
   LayerOGL* GetFirstChildOGL();
 
   virtual void RenderLayer(int aPreviousFrameBuffer,