Bug 570620, part i: Implement ShadowLayer::Disconnect() for common-case shutdown, and ShadowableLayer::Disconnect() for emergency-case shutdown. r=vlad
authorChris Jones <jones.chris.g@gmail.com>
Fri, 20 Aug 2010 18:24:41 -0500
changeset 54013 dc39260535b2a43b1d47f747dd1277de016f7f09
parent 54012 1a2663f57705337fe0ae80e5893519a7348ba17f
child 54014 84f9361915784a64ae48bf25c53d259ec8bdaf16
push idunknown
push userunknown
push dateunknown
reviewersvlad
bugs570620
milestone2.0b5pre
Bug 570620, part i: Implement ShadowLayer::Disconnect() for common-case shutdown, and ShadowableLayer::Disconnect() for emergency-case shutdown. r=vlad
gfx/layers/Makefile.in
gfx/layers/basic/BasicLayers.cpp
gfx/layers/ipc/ShadowLayerChild.cpp
gfx/layers/ipc/ShadowLayerChild.h
gfx/layers/ipc/ShadowLayerParent.cpp
gfx/layers/ipc/ShadowLayerParent.h
gfx/layers/ipc/ShadowLayersChild.cpp
gfx/layers/ipc/ShadowLayersChild.h
--- a/gfx/layers/Makefile.in
+++ b/gfx/layers/Makefile.in
@@ -100,20 +100,24 @@ CPPSRCS += \
         $(NULL)
 endif
 endif
 
 ifdef MOZ_IPC #{
 EXPORTS_NAMESPACES = mozilla/layers
 EXPORTS_mozilla/layers =\
         ShadowLayers.h \
+        ShadowLayersChild.h \
+        ShadowLayersParent.h \
         $(NULL)
 
 CPPSRCS += \
         ShadowLayers.cpp \
+        ShadowLayerChild.cpp \
+        ShadowLayersChild.cpp \
         ShadowLayerParent.cpp \
         ShadowLayersParent.cpp \
         $(NULL)
 endif #}
 
 # Enable GLES2.0 under maemo
 ifdef MOZ_X11
 ifdef MOZ_PLATFORM_MAEMO
@@ -130,9 +134,8 @@ endif
 CXXFLAGS += $(MOZ_CAIRO_CFLAGS)
 
 LayerManagerOGLShaders.h: LayerManagerOGLShaders.txt genshaders.py $(GLOBAL_DEPS)
 	$(PYTHON) $(srcdir)/opengl/genshaders.py $< $@
 
 LayerManagerOGL.$(OBJ_SUFFIX): LayerManagerOGLShaders.h
 
 GARBAGE += LayerManagerOGLShaders.h
-
--- a/gfx/layers/basic/BasicLayers.cpp
+++ b/gfx/layers/basic/BasicLayers.cpp
@@ -1172,16 +1172,26 @@ public:
     NS_ABORT_IF_FALSE(!mShadow, "can't have two shadows (yet)");
     mShadow = aShadow;
   }
 
   virtual void SetBackBuffer(gfxSharedImageSurface* aBuffer)
   {
     NS_RUNTIMEABORT("if this default impl is called, |aBuffer| leaks");
   }
+
+  virtual void Disconnect()
+  {
+    // This is an "emergency Disconnect()", called when the compositing
+    // process has died.  |mShadow| and our Shmem buffers are
+    // automatically managed by IPDL, so we don't need to explicitly
+    // free them here (it's hard to get that right on emergency
+    // shutdown anyway).
+    mShadow = nsnull;
+  }
 };
 
 static ShadowableLayer*
 ToShadowable(Layer* aLayer)
 {
   return ToData(aLayer)->AsShadowableLayer();
 }
 
@@ -1207,16 +1217,21 @@ public:
   }
 
   virtual void InsertAfter(Layer* aChild, Layer* aAfter);
   virtual void RemoveChild(Layer* aChild);
 
   virtual Layer* AsLayer() { return this; }
   virtual ShadowableLayer* AsShadowableLayer() { return this; }
 
+  virtual void Disconnect()
+  {
+    BasicShadowableLayer::Disconnect();
+  }
+
 private:
   BasicShadowLayerManager* ShadowManager()
   {
     return static_cast<BasicShadowLayerManager*>(mManager);
   }
 };
 
 void
@@ -1266,16 +1281,22 @@ public:
   virtual Layer* AsLayer() { return this; }
   virtual ShadowableLayer* AsShadowableLayer() { return this; }
 
   virtual void SetBackBuffer(gfxSharedImageSurface* aBuffer)
   {
     mBackBuffer = aBuffer;
   }
 
+  virtual void Disconnect()
+  {
+    mBackBuffer = nsnull;
+    BasicShadowableLayer::Disconnect();
+  }
+
 private:
   BasicShadowLayerManager* BasicManager()
   {
     return static_cast<BasicShadowLayerManager*>(mManager);
   }
 
   NS_OVERRIDE virtual void
   PaintBuffer(gfxContext* aContext,
@@ -1370,16 +1391,22 @@ public:
   virtual Layer* AsLayer() { return this; }
   virtual ShadowableLayer* AsShadowableLayer() { return this; }
 
   virtual void SetBackBuffer(gfxSharedImageSurface* aBuffer)
   {
     mBackSurface = aBuffer;
   }
 
+  virtual void Disconnect()
+  {
+    mBackSurface = nsnull;
+    BasicShadowableLayer::Disconnect();
+  }
+
 private:
   BasicShadowLayerManager* BasicManager()
   {
     return static_cast<BasicShadowLayerManager*>(mManager);
   }
 
   nsRefPtr<gfxSharedImageSurface> mBackSurface;
 };
@@ -1434,16 +1461,21 @@ public:
 
   virtual void FillSpecificAttributes(SpecificLayerAttributes& aAttrs)
   {
     aAttrs = ColorLayerAttributes(GetColor());
   }
 
   virtual Layer* AsLayer() { return this; }
   virtual ShadowableLayer* AsShadowableLayer() { return this; }
+
+  virtual void Disconnect()
+  {
+    BasicShadowableLayer::Disconnect();
+  }
 };
 
 class BasicShadowableCanvasLayer : public BasicCanvasLayer,
                                    public BasicShadowableLayer
 {
 public:
   BasicShadowableCanvasLayer(BasicShadowLayerManager* aManager) :
     BasicCanvasLayer(aManager)
@@ -1471,16 +1503,22 @@ public:
 
   virtual Layer* AsLayer() { return this; }
   virtual ShadowableLayer* AsShadowableLayer() { return this; }
 
   virtual void SetBackBuffer(gfxSharedImageSurface* aBuffer)
   {
     mBackBuffer = aBuffer;
   }
+ 
+  virtual void Disconnect()
+  {
+    mBackBuffer = nsnull;
+    BasicShadowableLayer::Disconnect();
+  }
 
 private:
   BasicShadowLayerManager* BasicManager()
   {
     return static_cast<BasicShadowLayerManager*>(mManager);
   }
 
   nsRefPtr<gfxSharedImageSurface> mBackBuffer;
@@ -1562,17 +1600,25 @@ protected:
 
 class BasicShadowThebesLayer : public ShadowThebesLayer, BasicImplData {
 public:
   BasicShadowThebesLayer(BasicShadowLayerManager* aLayerManager) :
     ShadowThebesLayer(aLayerManager, static_cast<BasicImplData*>(this))
   {
     MOZ_COUNT_CTOR(BasicShadowThebesLayer);
   }
-  virtual ~BasicShadowThebesLayer();
+  virtual ~BasicShadowThebesLayer()
+  {
+    // If Disconnect() wasn't called on us, then we assume that the
+    // remote side shut down and IPC is disconnected, so we let IPDL
+    // clean up our front surface Shmem.
+    MOZ_COUNT_DTOR(BasicShadowThebesLayer);
+  }
+
+  virtual void Disconnect();
 
   virtual already_AddRefed<gfxSharedImageSurface>
   Swap(gfxSharedImageSurface* aNewFront,
        const nsIntRect& aBufferRect,
        const nsIntPoint& aRotation)
   {
     return mFrontBuffer.Swap(aNewFront, aBufferRect, aRotation);
   }
@@ -1586,38 +1632,43 @@ private:
   BasicShadowLayerManager* BasicManager()
   {
     return static_cast<BasicShadowLayerManager*>(mManager);
   }
 
   ShadowThebesLayerBuffer mFrontBuffer;
 };
 
-BasicShadowThebesLayer::~BasicShadowThebesLayer()
+void
+BasicShadowThebesLayer::Disconnect()
 {
   nsRefPtr<gfxSharedImageSurface> frontBuffer =
     mFrontBuffer.Swap(0, nsIntRect());
   if (frontBuffer) {
     BasicManager()->ShadowLayerManager::DestroySharedSurface(frontBuffer);
   }
 
-  MOZ_COUNT_DTOR(BasicShadowThebesLayer);
+  ShadowThebesLayer::Disconnect();
 }
 
 void
 BasicShadowThebesLayer::Paint(gfxContext* aContext,
                               LayerManager::DrawThebesLayerCallback aCallback,
                               void* aCallbackData,
                               float aOpacity)
 {
   NS_ASSERTION(BasicManager()->InDrawing(),
                "Can only draw in drawing phase");
   NS_ASSERTION(BasicManager()->IsRetained(),
                "ShadowThebesLayer makes no sense without retained mode");
 
+  if (!mFrontBuffer.GetBuffer()) {
+    return;
+  }
+
   gfxContext* target = BasicManager()->GetTarget();
   NS_ASSERTION(target, "We shouldn't be called if there's no target");
 
   nsRefPtr<gfxASurface> targetSurface = aContext->CurrentSurface();
   PRBool isOpaqueContent =
     (targetSurface->AreSimilarSurfacesSensitiveToContentType() &&
      aOpacity == 1.0 &&
      CanUseOpaqueSurface());
@@ -1630,22 +1681,21 @@ class BasicShadowImageLayer : public Sha
 public:
   BasicShadowImageLayer(BasicShadowLayerManager* aLayerManager) :
     ShadowImageLayer(aLayerManager, static_cast<BasicImplData*>(this))
   {
     MOZ_COUNT_CTOR(BasicShadowImageLayer);
   }
   virtual ~BasicShadowImageLayer()
   {
-    if (mFrontSurface) {
-      BasicManager()->ShadowLayerManager::DestroySharedSurface(mFrontSurface);
-    }
     MOZ_COUNT_DTOR(BasicShadowImageLayer);
   }
 
+  virtual void Disconnect();
+
   virtual PRBool Init(gfxSharedImageSurface* front, const nsIntSize& size);
 
   virtual already_AddRefed<gfxSharedImageSurface>
   Swap(gfxSharedImageSurface* newFront);
 
   virtual void Paint(gfxContext* aContext,
                      LayerManager::DrawThebesLayerCallback aCallback,
                      void* aCallbackData,
@@ -1657,16 +1707,27 @@ protected:
     return static_cast<BasicShadowLayerManager*>(mManager);
   }
 
   // XXX ShmemImage?
   nsRefPtr<gfxSharedImageSurface> mFrontSurface;
   gfxIntSize mSize;
 };
 
+void
+BasicShadowImageLayer::Disconnect()
+{
+  if (mFrontSurface) {
+    BasicManager()->ShadowLayerManager::DestroySharedSurface(mFrontSurface);
+  }
+  mFrontSurface = nsnull;
+
+  ShadowImageLayer::Disconnect();
+}
+
 PRBool
 BasicShadowImageLayer::Init(gfxSharedImageSurface* front,
                             const nsIntSize& size)
 {
   mFrontSurface = front;
   mSize = gfxIntSize(size.width, size.height);
   return PR_TRUE;
 }
@@ -1680,38 +1741,41 @@ BasicShadowImageLayer::Swap(gfxSharedIma
 }
 
 void
 BasicShadowImageLayer::Paint(gfxContext* aContext,
                              LayerManager::DrawThebesLayerCallback aCallback,
                              void* aCallbackData,
                              float aOpacity)
 {
+  if (!mFrontSurface) {
+    return;
+  }
+
   nsRefPtr<gfxPattern> pat = new gfxPattern(mFrontSurface);
   pat->SetFilter(mFilter);
   BasicImageLayer::PaintContext(pat, mSize, aOpacity, aContext);
 }
 
 class BasicShadowCanvasLayer : public ShadowCanvasLayer,
                                BasicImplData
 {
 public:
   BasicShadowCanvasLayer(BasicShadowLayerManager* aLayerManager) :
     ShadowCanvasLayer(aLayerManager, static_cast<BasicImplData*>(this))
   {
     MOZ_COUNT_CTOR(BasicShadowCanvasLayer);
   }
   virtual ~BasicShadowCanvasLayer()
   {
-    if (mFrontSurface) {
-      BasicManager()->ShadowLayerManager::DestroySharedSurface(mFrontSurface);
-    }
     MOZ_COUNT_DTOR(BasicShadowCanvasLayer);
   }
 
+  virtual void Disconnect();
+
   virtual void Initialize(const Data& aData);
 
   virtual void Updated(const nsIntRect& aRect)
   {}
 
   virtual already_AddRefed<gfxSharedImageSurface>
   Swap(gfxSharedImageSurface* newFront);
 
@@ -1726,16 +1790,27 @@ private:
     return static_cast<BasicShadowLayerManager*>(mManager);
   }
 
   nsRefPtr<gfxSharedImageSurface> mFrontSurface;
   nsIntRect mBounds;
 };
 
 void
+BasicShadowCanvasLayer::Disconnect()
+{
+  if (mFrontSurface) {
+    BasicManager()->ShadowLayerManager::DestroySharedSurface(mFrontSurface);
+  }
+  mFrontSurface = nsnull;
+
+  ShadowCanvasLayer::Disconnect();
+}
+
+void
 BasicShadowCanvasLayer::Initialize(const Data& aData)
 {
   NS_ASSERTION(mFrontSurface == nsnull,
                "BasicCanvasLayer::Initialize called twice!");
   NS_ASSERTION(aData.mSurface && !aData.mGLContext, "no comprende OpenGL!");
 
   mFrontSurface = static_cast<gfxSharedImageSurface*>(aData.mSurface);
   mBounds.SetRect(0, 0, aData.mSize.width, aData.mSize.height);
@@ -1750,21 +1825,23 @@ BasicShadowCanvasLayer::Swap(gfxSharedIm
 }
 
 void
 BasicShadowCanvasLayer::Paint(gfxContext* aContext,
                               LayerManager::DrawThebesLayerCallback aCallback,
                               void* aCallbackData,
                               float aOpacity)
 {
-  MOZ_LAYERS_LOG(("[ShadowLayersChild] %s()", __FUNCTION__));
-
   NS_ASSERTION(BasicManager()->InDrawing(),
                "Can only draw in drawing phase");
 
+  if (!mFrontSurface) {
+    return;
+  }
+
   nsRefPtr<gfxPattern> pat = new gfxPattern(mFrontSurface);
 
   pat->SetFilter(mFilter);
   pat->SetExtend(gfxPattern::EXTEND_PAD);
 
   gfxRect r(0, 0, mBounds.width, mBounds.height);
   aContext->NewPath();
   aContext->PixelSnappedRectangleAndSetPattern(r, pat);
new file mode 100644
--- /dev/null
+++ b/gfx/layers/ipc/ShadowLayerChild.cpp
@@ -0,0 +1,71 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: sw=2 ts=8 et :
+ */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at:
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Code.
+ *
+ * The Initial Developer of the Original Code is
+ *   The Mozilla Foundation
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Chris Jones <jones.chris.g@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "ShadowLayerChild.h"
+#include "Layers.h"
+#include "ShadowLayers.h"
+
+namespace mozilla {
+namespace layers {
+
+ShadowLayerChild::ShadowLayerChild(ShadowableLayer* aLayer)
+  : mLayer(aLayer)
+{ }
+
+ShadowLayerChild::~ShadowLayerChild()
+{ }
+
+void
+ShadowLayerChild::ActorDestroy(ActorDestroyReason why)
+{
+  NS_ABORT_IF_FALSE(AncestorDeletion != why,
+                    "shadowable layer should have been cleaned up by now");
+
+  if (AbnormalShutdown == why) {
+    // This is last-ditch emergency shutdown.  Just have the layer
+    // forget its IPDL resources; IPDL-generated code will clean up
+    // automatically in this case.
+    mLayer->AsLayer()->Disconnect();
+    mLayer = nsnull;
+  }
+}
+
+}  // namespace layers
+}  // namespace mozilla
--- a/gfx/layers/ipc/ShadowLayerChild.h
+++ b/gfx/layers/ipc/ShadowLayerChild.h
@@ -46,24 +46,25 @@
 namespace mozilla {
 namespace layers {
 
 class ShadowableLayer;
 
 class ShadowLayerChild : public PLayerChild
 {
 public:
-  ShadowLayerChild(ShadowableLayer* aLayer) : mLayer(aLayer)
-  { }
-
-  virtual ~ShadowLayerChild()
-  { }
+  ShadowLayerChild(ShadowableLayer* aLayer);
+  virtual ~ShadowLayerChild();
 
   ShadowableLayer* layer() const { return mLayer; }
 
+protected:
+  NS_OVERRIDE
+  virtual void ActorDestroy(ActorDestroyReason why);
+
 private:
   ShadowableLayer* mLayer;
 };
 
 } // namespace layers
 } // namespace mozilla
 
 #endif // ifndef mozilla_layers_ShadowLayerChild_h
--- a/gfx/layers/ipc/ShadowLayerParent.cpp
+++ b/gfx/layers/ipc/ShadowLayerParent.cpp
@@ -62,17 +62,32 @@ ShadowLayerParent::Bind(Layer* layer)
 }
 
 ContainerLayer*
 ShadowLayerParent::AsContainer() const
 {
   return static_cast<ContainerLayer*>(AsLayer());
 }
 
-bool
-ShadowLayerParent::Recv__delete__()
+void
+ShadowLayerParent::ActorDestroy(ActorDestroyReason why)
 {
+  switch (why) {
+  case AncestorDeletion:
+    NS_RUNTIMEABORT("shadow layer deleted out of order!");
+    return;                     // unreached
+
+  case Deletion:
+    mLayer->Disconnect();
+    break;
+
+  case AbnormalShutdown:
+  case NormalShutdown:
+    // let IPDL-generated code automatically clean up Shmems and so
+    // forth; our channel is disconnected anyway
+    break;
+  }
+
   mLayer = NULL;
-  return true;
 }
 
 } // namespace layers
 } // namespace mozilla
--- a/gfx/layers/ipc/ShadowLayerParent.h
+++ b/gfx/layers/ipc/ShadowLayerParent.h
@@ -59,17 +59,18 @@ public:
   virtual ~ShadowLayerParent();
 
   void Bind(Layer* layer);
 
   Layer* AsLayer() const { return mLayer; }
   ContainerLayer* AsContainer() const;
 
 private:
-  NS_OVERRIDE virtual bool Recv__delete__();
+  NS_OVERRIDE
+  virtual void ActorDestroy(ActorDestroyReason why);
 
   nsRefPtr<Layer> mLayer;
 };
 
 } // namespace layers
 } // namespace mozilla
 
 #endif // ifndef mozilla_layers_ShadowLayerParent_h
new file mode 100644
--- /dev/null
+++ b/gfx/layers/ipc/ShadowLayersChild.cpp
@@ -0,0 +1,75 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: sw=2 ts=8 et :
+ */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at:
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Code.
+ *
+ * The Initial Developer of the Original Code is
+ *   The Mozilla Foundation
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Chris Jones <jones.chris.g@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "ShadowLayerChild.h"
+#include "ShadowLayersChild.h"
+
+namespace mozilla {
+namespace layers {
+
+void
+ShadowLayersChild::Destroy()
+{
+  NS_ABORT_IF_FALSE(0 == ManagedPLayerChild().Length(),
+                    "layers should have been cleaned up by now");
+  //
+  // FIXME: uncomment this when we have a manager
+  //
+  //PLayersChild::Send__delete__(this);
+  // WARNING: |this| has gone to the great heap in the sky
+}
+
+PLayerChild*
+ShadowLayersChild::AllocPLayer()
+{
+  // we always use the "power-user" ctor
+  NS_RUNTIMEABORT("not reached");
+  return NULL;
+}
+
+bool
+ShadowLayersChild::DeallocPLayer(PLayerChild* actor)
+{
+  delete actor;
+  return true;
+}
+
+}  // namespace layers
+}  // namespace mozilla
--- a/gfx/layers/ipc/ShadowLayersChild.h
+++ b/gfx/layers/ipc/ShadowLayersChild.h
@@ -37,36 +37,36 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef mozilla_layers_ShadowLayersChild_h
 #define mozilla_layers_ShadowLayersChild_h
 
 #include "mozilla/layers/PLayersChild.h"
-#include "mozilla/layers/ShadowLayerChild.h"
 
 namespace mozilla {
 namespace layers {
 
 class ShadowLayersChild : public PLayersChild
 {
 public:
   ShadowLayersChild() { }
   ~ShadowLayersChild() { }
 
+  /**
+   * Clean this up, finishing with Send__delete__().
+   *
+   * It is expected (checked with an assert) that all shadow layers
+   * created by this have already been destroyed and
+   * Send__delete__()d by the time this method is called.
+   */
+  void Destroy();
+
 protected:
-  NS_OVERRIDE virtual PLayerChild* AllocPLayer() {
-    // we always use the "power-user" ctor
-    NS_RUNTIMEABORT("not reached");
-    return NULL;
-  }
-
-  NS_OVERRIDE virtual bool DeallocPLayer(PLayerChild* actor) {
-    delete actor;
-    return true;
-  }
+  NS_OVERRIDE virtual PLayerChild* AllocPLayer();
+  NS_OVERRIDE virtual bool DeallocPLayer(PLayerChild* actor);
 };
 
 } // namespace layers
 } // namespace mozilla
 
 #endif // ifndef mozilla_layers_ShadowLayersChild_h