Bug 567966: Part 1: Properly handle siblings and children. Also fix missing release on container destructor. r=vlad
authorBas Schouten <bschouten@mozilla.com>
Tue, 25 May 2010 09:37:19 +0200
changeset 42793 d17957dc3ae10ab124c0a94c052e5acfa33f826b
parent 42792 ec3dafe67d2b8f1b9de7c0daa523d1e0b5ac6dcf
child 42794 242cafe7bc40e54035a6fdc2b7170206731a7cbf
push idunknown
push userunknown
push dateunknown
reviewersvlad
bugs567966
milestone1.9.3a5pre
Bug 567966: Part 1: Properly handle siblings and children. Also fix missing release on container destructor. r=vlad
gfx/layers/d3d9/ContainerLayerD3D9.cpp
gfx/layers/d3d9/ContainerLayerD3D9.h
gfx/layers/d3d9/ImageLayerD3D9.h
gfx/layers/d3d9/LayerManagerD3D9.cpp
gfx/layers/d3d9/LayerManagerD3D9.h
--- a/gfx/layers/d3d9/ContainerLayerD3D9.cpp
+++ b/gfx/layers/d3d9/ContainerLayerD3D9.cpp
@@ -42,70 +42,96 @@ namespace layers {
 
 ContainerLayerD3D9::ContainerLayerD3D9(LayerManagerD3D9 *aManager)
   : ContainerLayer(aManager, NULL)
   , LayerD3D9(aManager)
 {
   mImplData = static_cast<LayerD3D9*>(this);
 }
 
+ContainerLayerD3D9::~ContainerLayerD3D9()
+{
+  while (mFirstChild) {
+    Layer* next = mFirstChild->GetNextSibling();
+    mFirstChild->SetNextSibling(nsnull);
+    mFirstChild->SetPrevSibling(nsnull);
+    mFirstChild->SetParent(nsnull);
+    NS_RELEASE(mFirstChild);
+    mFirstChild = next;
+  }
+}
+
 const nsIntRect&
 ContainerLayerD3D9::GetVisibleRect()
 {
   return mVisibleRect;
 }
 
 void
 ContainerLayerD3D9::SetVisibleRegion(const nsIntRegion &aRegion)
 {
   mVisibleRect = aRegion.GetBounds();
 }
 
 void
 ContainerLayerD3D9::InsertAfter(Layer* aChild, Layer* aAfter)
 {
-  LayerD3D9 *newChild = static_cast<LayerD3D9*>(aChild->ImplData());
   aChild->SetParent(this);
   if (!aAfter) {
-    LayerD3D9 *oldFirstChild = GetFirstChildD3D9();
-    mFirstChild = newChild->GetLayer();
-    newChild->SetNextSibling(oldFirstChild);
+    Layer *oldFirstChild = GetFirstChild();
+    mFirstChild = aChild;
+    aChild->SetNextSibling(oldFirstChild);
+    aChild->SetPrevSibling(nsnull);
+    if (oldFirstChild) {
+      oldFirstChild->SetPrevSibling(aChild);
+    }
     NS_ADDREF(aChild);
     return;
   }
-  for (LayerD3D9 *child = GetFirstChildD3D9(); 
-    child; child = child->GetNextSibling()) {
-    if (aAfter == child->GetLayer()) {
-      LayerD3D9 *oldNextSibling = child->GetNextSibling();
-      child->SetNextSibling(newChild);
-      child->GetNextSibling()->SetNextSibling(oldNextSibling);
+  for (Layer *child = GetFirstChild(); 
+       child; child = child->GetNextSibling()) {
+    if (aAfter == child) {
+      Layer *oldNextSibling = child->GetNextSibling();
+      child->SetNextSibling(aChild);
+      aChild->SetNextSibling(oldNextSibling);
+      if (oldNextSibling) {
+        oldNextSibling->SetPrevSibling(aChild);
+      }
+      aChild->SetPrevSibling(child);
       NS_ADDREF(aChild);
       return;
     }
   }
   NS_WARNING("Failed to find aAfter layer!");
 }
 
 void
 ContainerLayerD3D9::RemoveChild(Layer *aChild)
 {
   if (GetFirstChild() == aChild) {
-    mFirstChild = GetFirstChildD3D9()->GetNextSibling() ?
-      GetFirstChildD3D9()->GetNextSibling()->GetLayer() : nsnull;
+    mFirstChild = GetFirstChild()->GetNextSibling() ?
+      GetFirstChild()->GetNextSibling() : nsnull;
+    if (mFirstChild) {
+      mFirstChild->SetPrevSibling(nsnull);
+    }
     NS_RELEASE(aChild);
     return;
   }
-  LayerD3D9 *lastChild = NULL;
-  for (LayerD3D9 *child = GetFirstChildD3D9(); child; 
-    child = child->GetNextSibling()) {
-    if (child->GetLayer() == aChild) {
+  Layer *lastChild = nsnull;
+  for (Layer *child = GetFirstChild(); child; 
+       child = child->GetNextSibling()) {
+    if (child == aChild) {
       // We're sure this is not our first child. So lastChild != NULL.
       lastChild->SetNextSibling(child->GetNextSibling());
-      child->SetNextSibling(NULL);
-      child->GetLayer()->SetParent(NULL);
+      if (child->GetNextSibling()) {
+        child->GetNextSibling()->SetPrevSibling(lastChild);
+      }
+      child->SetNextSibling(nsnull);
+      child->SetPrevSibling(nsnull);
+      child->SetParent(nsnull);
       NS_RELEASE(aChild);
       return;
     }
     lastChild = child;
   }
 }
 
 LayerD3D9::LayerType
@@ -205,17 +231,20 @@ ContainerLayerD3D9::RenderLayer()
     r.left = NS_MAX<LONG>(0, r.left);
     r.top = NS_MAX<LONG>(0, r.top);
     r.bottom = NS_MIN<LONG>(r.bottom, desc.Height);
     r.right = NS_MIN<LONG>(r.right, desc.Width);
 
     device()->SetScissorRect(&r);
 
     layerToRender->RenderLayer();
-    layerToRender = layerToRender->GetNextSibling();
+    Layer *nextSibling = layerToRender->GetLayer()->GetNextSibling();
+    layerToRender = nextSibling ? static_cast<LayerD3D9*>(nextSibling->
+                                                          ImplData())
+                                : nsnull;
   }
 
   if (useIntermediate) {
     device()->SetRenderTarget(0, previousRenderTarget);
     device()->SetVertexShaderConstantF(12, previousRenderTargetOffset, 1);
     device()->SetVertexShaderConstantF(8, &oldViewMatrix[0][0], 4);
 
     float quadTransform[4][4];
--- a/gfx/layers/d3d9/ContainerLayerD3D9.h
+++ b/gfx/layers/d3d9/ContainerLayerD3D9.h
@@ -40,20 +40,21 @@
 
 #include "Layers.h"
 #include "LayerManagerD3D9.h"
 
 namespace mozilla {
 namespace layers {
 
 class ContainerLayerD3D9 : public ContainerLayer, 
-                          public LayerD3D9
+                           public LayerD3D9
 {
 public:
   ContainerLayerD3D9(LayerManagerD3D9 *aManager);
+  ~ContainerLayerD3D9();
 
   const nsIntRect &GetVisibleRect();
 
   /* ContainerLayer implementation */
   void SetVisibleRegion(const nsIntRegion& aRegion);
 
   void InsertAfter(Layer* aChild, Layer* aAfter);
 
--- a/gfx/layers/d3d9/ImageLayerD3D9.h
+++ b/gfx/layers/d3d9/ImageLayerD3D9.h
@@ -95,16 +95,17 @@ public:
   virtual already_AddRefed<gfxASurface> GetAsSurface() = 0;
 };
 
 class THEBES_API PlanarYCbCrImageD3D9 : public PlanarYCbCrImage,
                                         public ImageD3D9
 {
 public:
   PlanarYCbCrImageD3D9(LayerManagerD3D9 *aManager);
+  ~PlanarYCbCrImageD3D9() {}
 
   virtual void SetData(const Data &aData);
 
   /*
    * Upload the data from out mData into our textures. For now we use this to
    * make sure the textures are created and filled on the main thread.
    */
   void AllocateTextures();
--- a/gfx/layers/d3d9/LayerManagerD3D9.cpp
+++ b/gfx/layers/d3d9/LayerManagerD3D9.cpp
@@ -553,26 +553,13 @@ LayerManagerD3D9::VerifyCaps()
       (caps.VertexShaderVersion & 0xffff) < 0x200) {
     return PR_FALSE;
   }
   return PR_TRUE;
 }
 
 LayerD3D9::LayerD3D9(LayerManagerD3D9 *aManager)
   : mD3DManager(aManager)
-  , mNextSibling(NULL)
 {
 }
 
-LayerD3D9*
-LayerD3D9::GetNextSibling()
-{
-  return mNextSibling;
-}
-
-void
-LayerD3D9::SetNextSibling(LayerD3D9 *aNextSibling)
-{
-  mNextSibling = aNextSibling;
-}
-
 } /* namespace layers */
 } /* namespace mozilla */
--- a/gfx/layers/d3d9/LayerManagerD3D9.h
+++ b/gfx/layers/d3d9/LayerManagerD3D9.h
@@ -212,28 +212,25 @@ class LayerD3D9
 public:
   LayerD3D9(LayerManagerD3D9 *aManager);
 
   enum LayerType { TYPE_THEBES, TYPE_CONTAINER, TYPE_IMAGE, TYPE_COLOR,
                    TYPE_CANVAS };
   
   virtual LayerType GetType() = 0;
 
-  LayerD3D9 *GetNextSibling();
   virtual LayerD3D9 *GetFirstChildD3D9() { return nsnull; }
 
-  void SetNextSibling(LayerD3D9 *aParent);
   void SetFirstChild(LayerD3D9 *aParent);
 
   virtual Layer* GetLayer() = 0;
 
   virtual void RenderLayer() = 0;
 
   IDirect3DDevice9 *device() const { return mD3DManager->device(); }
 protected:
   LayerManagerD3D9 *mD3DManager;
-  LayerD3D9 *mNextSibling;
 };
 
 } /* layers */
 } /* mozilla */
 
 #endif /* GFX_LAYERMANAGERD3D9_H */