Bug 623255: Ensure LayerOGL::Destroy is called for "orphaned" shadow OGL layers before the GLContext is deleted. r=vlad a=b
authorChris Jones <jones.chris.g@gmail.com>
Wed, 05 Jan 2011 22:54:47 -0600
changeset 60065 9a10911e5b290e5a8d02bf751b2283882a4d4d27
parent 60064 79c44d25229d7bdb81f5c29ba4cc35c676a03efc
child 60066 57103cddaf3729cfeeac33355ab7110995fb4bd3
push id17845
push usercjones@mozilla.com
push dateThu, 06 Jan 2011 04:55:05 +0000
treeherdermozilla-central@9a10911e5b29 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersvlad, b
bugs623255
milestone2.0b9pre
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 623255: Ensure LayerOGL::Destroy is called for "orphaned" shadow OGL layers before the GLContext is deleted. r=vlad a=b
content/base/src/nsFrameLoader.cpp
dom/ipc/TabParent.cpp
dom/ipc/TabParent.h
gfx/layers/ipc/ShadowLayerParent.cpp
gfx/layers/ipc/ShadowLayerParent.h
gfx/layers/ipc/ShadowLayersParent.cpp
gfx/layers/ipc/ShadowLayersParent.h
gfx/layers/opengl/CanvasLayerOGL.cpp
gfx/layers/opengl/CanvasLayerOGL.h
gfx/layers/opengl/ImageLayerOGL.cpp
gfx/layers/opengl/ImageLayerOGL.h
gfx/layers/opengl/ThebesLayerOGL.cpp
gfx/layers/opengl/ThebesLayerOGL.h
layout/ipc/RenderFrameParent.cpp
layout/ipc/RenderFrameParent.h
--- a/content/base/src/nsFrameLoader.cpp
+++ b/content/base/src/nsFrameLoader.cpp
@@ -1062,20 +1062,17 @@ nsFrameLoader::SwapWithOtherLoader(nsFra
 }
 
 void
 nsFrameLoader::DestroyChild()
 {
 #ifdef MOZ_IPC
   if (mRemoteBrowser) {
     mRemoteBrowser->SetOwnerElement(nsnull);
-    // If this fails, it's most likely due to a content-process crash,
-    // and auto-cleanup will kick in.  Otherwise, the child side will
-    // destroy itself and send back __delete__().
-    unused << mRemoteBrowser->SendDestroy();
+    mRemoteBrowser->Destroy();
     mRemoteBrowser = nsnull;
   }
 #endif
 }
 
 NS_IMETHODIMP
 nsFrameLoader::Destroy()
 {
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -106,16 +106,31 @@ TabParent::SetOwnerElement(nsIDOMElement
   if (aElement) {
     nsCOMPtr<nsIWidget> widget = GetWidget();
     NS_ABORT_IF_FALSE(widget, "Non-null OwnerElement must provide a widget!");
     mDPI = widget->GetDPI();
   }
 }
 
 void
+TabParent::Destroy()
+{
+  // If this fails, it's most likely due to a content-process crash,
+  // and auto-cleanup will kick in.  Otherwise, the child side will
+  // destroy itself and send back __delete__().
+  unused << SendDestroy();
+
+  for (size_t i = 0; i < ManagedPRenderFrameParent().Length(); ++i) {
+    RenderFrameParent* rfp =
+      static_cast<RenderFrameParent*>(ManagedPRenderFrameParent()[i]);
+    rfp->Destroy();
+  }
+}
+
+void
 TabParent::ActorDestroy(ActorDestroyReason why)
 {
   nsRefPtr<nsFrameLoader> frameLoader = GetFrameLoader();
   if (frameLoader) {
     frameLoader->DestroyChild();
   }
 }
 
--- a/dom/ipc/TabParent.h
+++ b/dom/ipc/TabParent.h
@@ -75,16 +75,18 @@ public:
     virtual ~TabParent();
     nsIDOMElement* GetOwnerElement() { return mFrameElement; }
     void SetOwnerElement(nsIDOMElement* aElement);
     nsIBrowserDOMWindow *GetBrowserDOMWindow() { return mBrowserDOMWindow; }
     void SetBrowserDOMWindow(nsIBrowserDOMWindow* aBrowserDOMWindow) {
         mBrowserDOMWindow = aBrowserDOMWindow;
     }
  
+    void Destroy();
+
     virtual bool RecvMoveFocus(const bool& aForward);
     virtual bool RecvEvent(const RemoteDOMEvent& aEvent);
 
     virtual bool AnswerCreateWindow(PBrowserParent** retval);
     virtual bool RecvSyncMessage(const nsString& aMessage,
                                  const nsString& aJSON,
                                  InfallibleTArray<nsString>* aJSONRetVal);
     virtual bool RecvAsyncMessage(const nsString& aMessage,
--- a/gfx/layers/ipc/ShadowLayerParent.cpp
+++ b/gfx/layers/ipc/ShadowLayerParent.cpp
@@ -56,32 +56,47 @@ ShadowLayerParent::~ShadowLayerParent()
 }
 
 void
 ShadowLayerParent::Bind(Layer* layer)
 {
   mLayer = layer;
 }
 
+void
+ShadowLayerParent::Destroy()
+{
+  // It's possible for Destroy() to come in just after this has been
+  // created, but just before the transaction in which Bind() would
+  // have been called.  In that case, we'll ignore shadow-layers
+  // transactions from there on and never get a layer here.
+  if (mLayer) {
+    mLayer->Disconnect();
+  }
+}
+
 ContainerLayer*
 ShadowLayerParent::AsContainer() const
 {
   return static_cast<ContainerLayer*>(AsLayer());
 }
 
 void
 ShadowLayerParent::ActorDestroy(ActorDestroyReason why)
 {
   switch (why) {
   case AncestorDeletion:
     NS_RUNTIMEABORT("shadow layer deleted out of order!");
     return;                     // unreached
 
   case Deletion:
-    mLayer->Disconnect();
+    // See comment near Destroy() above.
+    if (mLayer) {
+      mLayer->Disconnect();
+    }
     break;
 
   case AbnormalShutdown:
   case NormalShutdown:
     // let IPDL-generated code automatically clean up Shmems and so
     // forth; our channel is disconnected anyway
     break;
   }
--- a/gfx/layers/ipc/ShadowLayerParent.h
+++ b/gfx/layers/ipc/ShadowLayerParent.h
@@ -54,16 +54,17 @@ class ShadowLayersParent;
 class ShadowLayerParent : public PLayerParent
 {
 public:
   ShadowLayerParent();
 
   virtual ~ShadowLayerParent();
 
   void Bind(Layer* layer);
+  void Destroy();
 
   Layer* AsLayer() const { return mLayer; }
   ContainerLayer* AsContainer() const;
 
 private:
   NS_OVERRIDE
   virtual void ActorDestroy(ActorDestroyReason why);
 
--- a/gfx/layers/ipc/ShadowLayersParent.cpp
+++ b/gfx/layers/ipc/ShadowLayersParent.cpp
@@ -127,16 +127,26 @@ ShadowLayersParent::ShadowLayersParent(S
   mLayerManager = aManager;
 }
 
 ShadowLayersParent::~ShadowLayersParent()
 {
   MOZ_COUNT_DTOR(ShadowLayersParent);
 }
 
+void
+ShadowLayersParent::Destroy()
+{
+  for (size_t i = 0; i < ManagedPLayerParent().Length(); ++i) {
+    ShadowLayerParent* slp =
+      static_cast<ShadowLayerParent*>(ManagedPLayerParent()[i]);
+    slp->Destroy();
+  }
+}
+
 bool
 ShadowLayersParent::RecvUpdate(const InfallibleTArray<Edit>& cset,
                                InfallibleTArray<EditReply>* reply)
 {
   MOZ_LAYERS_LOG(("[ParentSide] recieved txn with %d edits", cset.Length()));
 
   EditReplyVector replyv;
 
--- a/gfx/layers/ipc/ShadowLayersParent.h
+++ b/gfx/layers/ipc/ShadowLayersParent.h
@@ -59,16 +59,18 @@ class ShadowLayersParent : public PLayer
   typedef mozilla::layout::RenderFrameParent RenderFrameParent;
   typedef InfallibleTArray<Edit> EditArray;
   typedef InfallibleTArray<EditReply> EditReplyArray;
 
 public:
   ShadowLayersParent(ShadowLayerManager* aManager);
   ~ShadowLayersParent();
 
+  void Destroy();
+
   ShadowLayerManager* layer_manager() const { return mLayerManager; }
 
   ContainerLayer* GetRoot() const { return mRoot; }
 
 protected:
   NS_OVERRIDE virtual bool RecvUpdate(const EditArray& cset,
                                       EditReplyArray* reply);
 
--- a/gfx/layers/opengl/CanvasLayerOGL.cpp
+++ b/gfx/layers/opengl/CanvasLayerOGL.cpp
@@ -297,16 +297,22 @@ ShadowCanvasLayerOGL::DestroyFrontBuffer
   mTexImage = nsnull;
   if (mDeadweight) {
     mOGLManager->DestroySharedSurface(mDeadweight, mAllocator);
     mDeadweight = nsnull;
   }
 }
 
 void
+ShadowCanvasLayerOGL::Disconnect()
+{
+  Destroy();
+}
+
+void
 ShadowCanvasLayerOGL::Destroy()
 {
   if (!mDestroyed) {
     mDestroyed = PR_TRUE;
     mTexImage = nsnull;
   }
 }
 
--- a/gfx/layers/opengl/CanvasLayerOGL.h
+++ b/gfx/layers/opengl/CanvasLayerOGL.h
@@ -108,16 +108,18 @@ public:
   virtual void Updated(const nsIntRect&) {}
 
   // ShadowCanvasLayer impl
   virtual already_AddRefed<gfxSharedImageSurface>
   Swap(gfxSharedImageSurface* aNewFront);
 
   virtual void DestroyFrontBuffer();
 
+  virtual void Disconnect();
+
   // LayerOGL impl
   void Destroy();
   Layer* GetLayer();
   virtual void RenderLayer(int aPreviousFrameBuffer,
                            const nsIntPoint& aOffset);
 
 private:
   nsRefPtr<TextureImage> mTexImage;
--- a/gfx/layers/opengl/ImageLayerOGL.cpp
+++ b/gfx/layers/opengl/ImageLayerOGL.cpp
@@ -747,16 +747,22 @@ ShadowImageLayerOGL::DestroyFrontBuffer(
   mTexImage = nsnull;
   if (mDeadweight) {
     mOGLManager->DestroySharedSurface(mDeadweight, mAllocator);
     mDeadweight = nsnull;
   }
 }
 
 void
+ShadowImageLayerOGL::Disconnect()
+{
+  Destroy();
+}
+
+void
 ShadowImageLayerOGL::Destroy()
 {
   if (!mDestroyed) {
     mDestroyed = PR_TRUE;
     mTexImage = nsnull;
   }
 }
 
--- a/gfx/layers/opengl/ImageLayerOGL.h
+++ b/gfx/layers/opengl/ImageLayerOGL.h
@@ -254,16 +254,18 @@ public:
   // ShadowImageLayer impl
   virtual PRBool Init(gfxSharedImageSurface* aFront, const nsIntSize& aSize);
 
   virtual already_AddRefed<gfxSharedImageSurface>
   Swap(gfxSharedImageSurface* aNewFront);
 
   virtual void DestroyFrontBuffer();
 
+  virtual void Disconnect();
+
   // LayerOGL impl
   virtual void Destroy();
 
   virtual Layer* GetLayer();
 
   virtual void RenderLayer(int aPreviousFrameBuffer,
                            const nsIntPoint& aOffset);
 
--- a/gfx/layers/opengl/ThebesLayerOGL.cpp
+++ b/gfx/layers/opengl/ThebesLayerOGL.cpp
@@ -705,16 +705,22 @@ ShadowThebesLayerOGL::Swap(const ThebesB
 
 void
 ShadowThebesLayerOGL::DestroyFrontBuffer()
 {
   mBuffer = nsnull;
 }
 
 void
+ShadowThebesLayerOGL::Disconnect()
+{
+  Destroy();
+}
+
+void
 ShadowThebesLayerOGL::Destroy()
 {
   if (!mDestroyed) {
     mDestroyed = PR_TRUE;
     mBuffer = nsnull;
   }
 }
 
--- a/gfx/layers/opengl/ThebesLayerOGL.h
+++ b/gfx/layers/opengl/ThebesLayerOGL.h
@@ -100,16 +100,18 @@ public:
                               float aXResolution, float aYResolution);
   virtual void
   Swap(const ThebesBuffer& aNewFront, const nsIntRegion& aUpdatedRegion,
        ThebesBuffer* aNewBack, nsIntRegion* aNewBackValidRegion,
        float* aNewXResolution, float* aNewYResolution,
        OptionalThebesBuffer* aReadOnlyFront, nsIntRegion* aFrontUpdatedRegion);
   virtual void DestroyFrontBuffer();
 
+  virtual void Disconnect();
+
   // LayerOGL impl
   void Destroy();
   Layer* GetLayer();
   virtual PRBool IsEmpty();
   virtual void RenderLayer(int aPreviousFrameBuffer,
                            const nsIntPoint& aOffset);
 
 private:
--- a/layout/ipc/RenderFrameParent.cpp
+++ b/layout/ipc/RenderFrameParent.cpp
@@ -177,16 +177,30 @@ RenderFrameParent::RenderFrameParent(nsF
 {
   NS_ABORT_IF_FALSE(aFrameLoader, "Need a frameloader here");
 }
 
 RenderFrameParent::~RenderFrameParent()
 {}
 
 void
+RenderFrameParent::Destroy()
+{
+  size_t numChildren = ManagedPLayersParent().Length();
+  NS_ABORT_IF_FALSE(0 == numChildren || 1 == numChildren,
+                    "render frame must only have 0 or 1 layer manager");
+
+  if (numChildren) {
+    ShadowLayersParent* layers =
+      static_cast<ShadowLayersParent*>(ManagedPLayersParent()[0]);
+    layers->Destroy();
+  }
+}
+
+void
 RenderFrameParent::ShadowLayersUpdated()
 {
   mFrameLoader->SetCurrentRemoteFrame(this);
 
   nsIFrame* docFrame = mFrameLoader->GetPrimaryFrameOfOwningContent();
   if (!docFrame) {
     // Bad, but nothing we can do about it (XXX/cjones: or is there?
     // maybe bug 589337?).  When the new frame is created, we'll
--- a/layout/ipc/RenderFrameParent.h
+++ b/layout/ipc/RenderFrameParent.h
@@ -63,16 +63,18 @@ class RenderFrameParent : public PRender
   typedef mozilla::layers::Layer Layer;
   typedef mozilla::layers::LayerManager LayerManager;
   typedef mozilla::layers::ShadowLayersParent ShadowLayersParent;
 
 public:
   RenderFrameParent(nsFrameLoader* aFrameLoader);
   virtual ~RenderFrameParent();
 
+  void Destroy();
+
   void ShadowLayersUpdated();
 
   already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
                                      nsIFrame* aFrame,
                                      LayerManager* aManager,
                                      const nsIntRect& aVisibleRect);
 
 protected: