Bug 570294, part g: Implement basic ShadowLayers and share basic layers with remote processes. r=Bas sr=vlad
authorChris Jones <jones.chris.g@gmail.com>
Wed, 21 Jul 2010 16:17:33 -0500
changeset 48140 4515c729fe32b9aee03531341c9b80b029050b7b
parent 48139 f008f1965cc9bb8cd0b5bc2ac0c636615e1c1c00
child 48141 507ad177534a2027c077c2639c8707272b3af889
push idunknown
push userunknown
push dateunknown
reviewersBas, vlad
bugs570294
milestone2.0b3pre
Bug 570294, part g: Implement basic ShadowLayers and share basic layers with remote processes. r=Bas sr=vlad
gfx/layers/Makefile.in
gfx/layers/basic/BasicLayers.cpp
gfx/layers/basic/BasicLayers.h
--- a/gfx/layers/Makefile.in
+++ b/gfx/layers/Makefile.in
@@ -93,16 +93,21 @@ CPPSRCS += \
         ImageLayerD3D9.cpp \
         ColorLayerD3D9.cpp \
         CanvasLayerD3D9.cpp \
         $(NULL)
 endif
 endif
 
 ifdef MOZ_IPC #{
+EXPORTS_NAMESPACES = mozilla/layers
+EXPORTS_mozilla/layers =\
+        ShadowLayers.h \
+        $(NULL)
+
 CPPSRCS += \
         ShadowLayers.cpp \
         ShadowLayerParent.cpp \
         ShadowLayersParent.cpp \
         $(NULL)
 endif #}
 
 # Enable GLES2.0 under maemo
--- a/gfx/layers/basic/BasicLayers.cpp
+++ b/gfx/layers/basic/BasicLayers.cpp
@@ -15,31 +15,37 @@
  * The Original Code is Mozilla Corporation code.
  *
  * The Initial Developer of the Original Code is Mozilla Foundation.
  * Portions created by the Initial Developer are Copyright (C) 2009
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  *   Robert O'Callahan <robert@ocallahan.org>
+ *   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 ***** */
 
+#ifdef MOZ_IPC
+#  include "mozilla/layers/PLayerChild.h"
+#  include "mozilla/layers/PLayersChild.h"
+#endif
+
 #include "BasicLayers.h"
 #include "ImageLayers.h"
 
 #include "nsTArray.h"
 #include "nsGUIEvent.h"
 #include "nsIRenderingContext.h"
 #include "gfxContext.h"
 #include "gfxImageSurface.h"
@@ -50,16 +56,17 @@
 #include "nsIWidget.h"
 
 #include "GLContext.h"
 
 namespace mozilla {
 namespace layers {
 
 class BasicContainerLayer;
+class ShadowableLayer;
 
 /**
  * This is the ImplData for all Basic layers. It also exposes methods
  * private to the Basic implementation that are common to all Basic layer types.
  * In particular, there is an internal Paint() method that we can use
  * to paint the contents of non-Thebes layers.
  *
  * The class hierarchy for Basic layers is like this:
@@ -79,31 +86,33 @@ class BasicContainerLayer;
  *       +-> BasicImageLayer <--------------+
  */
 class BasicImplData {
 public:
   BasicImplData()
   {
     MOZ_COUNT_CTOR(BasicImplData);
   }
-  ~BasicImplData()
+  virtual ~BasicImplData()
   {
     MOZ_COUNT_DTOR(BasicImplData);
   }
 
   /**
    * Layers that paint themselves, such as ImageLayers, should paint
    * in response to this method call. aContext will already have been
    * set up to account for all the properties of the layer (transform,
    * opacity, etc).
    */
   virtual void Paint(gfxContext* aContext,
                      LayerManager::DrawThebesLayerCallback aCallback,
                      void* aCallbackData,
                      float aOpacity) {}
+
+  virtual ShadowableLayer* AsShadowableLayer() { return NULL; }
 };
 
 static BasicImplData*
 ToData(Layer* aLayer)
 {
   return static_cast<BasicImplData*>(aLayer->ImplData());
 }
 
@@ -652,16 +661,19 @@ BasicCanvasLayer::Updated(const nsIntRec
 }
 
 void
 BasicCanvasLayer::Paint(gfxContext* aContext,
                         LayerManager::DrawThebesLayerCallback aCallback,
                         void* aCallbackData,
                         float aOpacity)
 {
+  NS_ASSERTION(BasicManager()->InDrawing(),
+               "Can only draw in drawing phase");
+
   nsRefPtr<gfxPattern> pat = new gfxPattern(mSurface);
 
   pat->SetFilter(mFilter);
   pat->SetExtend(gfxPattern::EXTEND_PAD);
 
   gfxRect r(0, 0, mBounds.width, mBounds.height);
   gfxMatrix m;
   if (mNeedsYFlip) {
@@ -750,31 +762,31 @@ MayHaveOverlappingOrTransparentLayers(La
 
     region.Or(region, childRegion);
   }
 
   return PR_FALSE;
 }
 
 BasicLayerManager::BasicLayerManager(nsIWidget* aWidget) :
+#ifdef DEBUG
+  mPhase(PHASE_NONE),
+#endif
   mWidget(aWidget)
-#ifdef DEBUG
-  , mPhase(PHASE_NONE)
-#endif
   , mDoubleBuffering(BUFFER_NONE), mUsingDefaultTarget(PR_FALSE)
 {
   MOZ_COUNT_CTOR(BasicLayerManager);
   NS_ASSERTION(aWidget, "Must provide a widget");
 }
 
 BasicLayerManager::BasicLayerManager() :
+#ifdef DEBUG
+  mPhase(PHASE_NONE),
+#endif
   mWidget(nsnull)
-#ifdef DEBUG
-  , mPhase(PHASE_NONE)
-#endif
   , mDoubleBuffering(BUFFER_NONE), mUsingDefaultTarget(PR_FALSE)
 {
   MOZ_COUNT_CTOR(BasicLayerManager);
 }
 
 BasicLayerManager::~BasicLayerManager()
 {
   NS_ASSERTION(!InTransaction(), "Died during transaction?");
@@ -850,18 +862,18 @@ BasicLayerManager::BeginTransactionWithT
   mTarget = aTarget;
 }
 
 void
 BasicLayerManager::EndTransaction(DrawThebesLayerCallback aCallback,
                                   void* aCallbackData)
 {
 #ifdef MOZ_LAYERS_HAVE_LOG
+  MOZ_LAYERS_LOG(("  ----- (beginning paint)"));
   Log();
-  MOZ_LAYERS_LOG(("]----- EndTransaction"));
 #endif
 
   NS_ASSERTION(InConstruction(), "Should be in construction phase");
 #ifdef DEBUG
   mPhase = PHASE_DRAWING;
 #endif
 
   if (mTarget) {
@@ -887,16 +899,21 @@ BasicLayerManager::EndTransaction(DrawTh
     if (useDoubleBuffering) {
       finalTarget->SetOperator(gfxContext::OPERATOR_SOURCE);
       PopGroupWithCachedSurface(finalTarget, cachedSurfaceOffset);
     }
 
     mTarget = nsnull;
   }
 
+#ifdef MOZ_LAYERS_HAVE_LOG
+  Log();
+  MOZ_LAYERS_LOG(("]----- EndTransaction"));
+#endif
+
 #ifdef DEBUG
   mPhase = PHASE_NONE;
 #endif
   mUsingDefaultTarget = PR_FALSE;
 }
 
 void
 BasicLayerManager::SetRoot(Layer* aLayer)
@@ -1027,10 +1044,450 @@ BasicLayerManager::CreateColorLayer()
 already_AddRefed<CanvasLayer>
 BasicLayerManager::CreateCanvasLayer()
 {
   NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
   nsRefPtr<CanvasLayer> layer = new BasicCanvasLayer(this);
   return layer.forget();
 }
 
+
+#ifdef MOZ_IPC
+
+class BasicShadowableLayer : public ShadowableLayer
+{
+public:
+  BasicShadowableLayer()
+  {
+    MOZ_COUNT_CTOR(BasicShadowableLayer);
+  }
+
+  ~BasicShadowableLayer()
+  {
+    if (HasShadow()) {
+      PLayerChild::Send__delete__(GetShadow());
+    }
+    MOZ_COUNT_DTOR(BasicShadowableLayer);
+  }
+
+  void SetShadow(PLayerChild* aShadow)
+  {
+    NS_ABORT_IF_FALSE(!mShadow, "can't have two shadows (yet)");
+    mShadow = aShadow;
+  }
+};
+
+static ShadowableLayer*
+ToShadowable(Layer* aLayer)
+{
+  return ToData(aLayer)->AsShadowableLayer();
+}
+
+class BasicShadowableContainerLayer : public BasicContainerLayer,
+                                      public BasicShadowableLayer {
+public:
+  BasicShadowableContainerLayer(BasicShadowLayerManager* aManager) :
+    BasicContainerLayer(aManager)
+  {
+    MOZ_COUNT_CTOR(BasicShadowableContainerLayer);
+  }
+  virtual ~BasicShadowableContainerLayer()
+  {
+    MOZ_COUNT_DTOR(BasicShadowableContainerLayer);
+  }
+
+  virtual void InsertAfter(Layer* aChild, Layer* aAfter);
+  virtual void RemoveChild(Layer* aChild);
+
+  virtual Layer* AsLayer() { return this; }
+  virtual ShadowableLayer* AsShadowableLayer() { return this; }
+
+private:
+  BasicShadowLayerManager* ShadowManager()
+  {
+    return static_cast<BasicShadowLayerManager*>(mManager);
+  }
+};
+
+void
+BasicShadowableContainerLayer::InsertAfter(Layer* aChild, Layer* aAfter)
+{
+  if (HasShadow()) {
+    ShadowManager()->InsertAfter(ShadowManager()->Hold(this),
+                                 ShadowManager()->Hold(aChild),
+                                 aAfter ? ShadowManager()->Hold(aAfter) : NULL);
+  }
+  BasicContainerLayer::InsertAfter(aChild, aAfter);
+}
+
+void
+BasicShadowableContainerLayer::RemoveChild(Layer* aChild)
+{
+  if (HasShadow()) {
+    ShadowManager()->RemoveChild(ShadowManager()->Hold(this),
+                                 ShadowManager()->Hold(aChild));
+  }
+  BasicContainerLayer::RemoveChild(aChild);
+}
+
+class BasicShadowableThebesLayer : public BasicThebesLayer,
+                                   public BasicShadowableLayer
+{
+public:
+  BasicShadowableThebesLayer(BasicShadowLayerManager* aManager) :
+    BasicThebesLayer(aManager)
+  {
+    MOZ_COUNT_CTOR(BasicShadowableThebesLayer);
+  }
+  virtual ~BasicShadowableThebesLayer()
+  {
+    MOZ_COUNT_DTOR(BasicShadowableThebesLayer);
+  }
+
+  virtual void FillSpecificAttributes(SpecificLayerAttributes& aAttrs)
+  {
+    aAttrs = ThebesLayerAttributes(GetValidRegion());
+  }
+
+  virtual Layer* AsLayer() { return this; }
+  virtual ShadowableLayer* AsShadowableLayer() { return this; }
+};
+
+class BasicShadowableImageLayer : public BasicImageLayer,
+                                  public BasicShadowableLayer
+{
+public:
+  BasicShadowableImageLayer(BasicShadowLayerManager* aManager) :
+    BasicImageLayer(aManager)
+  {
+    MOZ_COUNT_CTOR(BasicShadowableImageLayer);
+  }
+  virtual ~BasicShadowableImageLayer()
+  {
+    MOZ_COUNT_DTOR(BasicShadowableImageLayer);
+  }
+
+  virtual void FillSpecificAttributes(SpecificLayerAttributes& aAttrs)
+  {
+    aAttrs = ImageLayerAttributes(mFilter);
+  }
+
+  virtual Layer* AsLayer() { return this; }
+  virtual ShadowableLayer* AsShadowableLayer() { return this; }
+};
+
+class BasicShadowableColorLayer : public BasicColorLayer,
+                                  public BasicShadowableLayer
+{
+public:
+  BasicShadowableColorLayer(BasicShadowLayerManager* aManager) :
+    BasicColorLayer(aManager)
+  {
+    MOZ_COUNT_CTOR(BasicShadowableColorLayer);
+  }
+  virtual ~BasicShadowableColorLayer()
+  {
+    MOZ_COUNT_DTOR(BasicShadowableColorLayer);
+  }
+
+  virtual void FillSpecificAttributes(SpecificLayerAttributes& aAttrs)
+  {
+    aAttrs = ColorLayerAttributes(GetColor());
+  }
+
+  virtual Layer* AsLayer() { return this; }
+  virtual ShadowableLayer* AsShadowableLayer() { return this; }
+};
+
+class BasicShadowableCanvasLayer : public BasicCanvasLayer,
+                                   public BasicShadowableLayer
+{
+public:
+  BasicShadowableCanvasLayer(BasicShadowLayerManager* aManager) :
+    BasicCanvasLayer(aManager)
+  {
+    MOZ_COUNT_CTOR(BasicShadowableCanvasLayer);
+  }
+  virtual ~BasicShadowableCanvasLayer()
+  {
+    MOZ_COUNT_DTOR(BasicShadowableCanvasLayer);
+  }
+
+  virtual void FillSpecificAttributes(SpecificLayerAttributes& aAttrs)
+  {
+    aAttrs = CanvasLayerAttributes(mFilter);
+  }
+
+  virtual Layer* AsLayer() { return this; }
+  virtual ShadowableLayer* AsShadowableLayer() { return this; }
+};
+
+class BasicShadowThebesLayer : public ShadowThebesLayer, BasicImplData {
+public:
+  BasicShadowThebesLayer(BasicShadowLayerManager* aLayerManager) :
+    ShadowThebesLayer(aLayerManager, static_cast<BasicImplData*>(this))
+  {
+    MOZ_COUNT_CTOR(BasicShadowThebesLayer);
+  }
+  virtual ~BasicShadowThebesLayer()
+  {
+    MOZ_COUNT_DTOR(BasicShadowThebesLayer);
+  }
+
+  virtual already_AddRefed<gfxSharedImageSurface>
+  Swap(gfxSharedImageSurface* aNewFront,
+       const nsIntRect& aBufferRect,
+       const nsIntPoint& aRotation)
+  { return NULL; }
+
+  virtual void Paint(gfxContext* aContext,
+                     LayerManager::DrawThebesLayerCallback aCallback,
+                     void* aCallbackData,
+                     float aOpacity)
+  {}
+
+  MOZ_LAYER_DECL_NAME("BasicShadowThebesLayer", TYPE_SHADOW)
+};
+
+class BasicShadowImageLayer : public ShadowImageLayer, BasicImplData {
+public:
+  BasicShadowImageLayer(BasicShadowLayerManager* aLayerManager) :
+    ShadowImageLayer(aLayerManager, static_cast<BasicImplData*>(this))
+  {
+    MOZ_COUNT_CTOR(BasicShadowImageLayer);
+  }
+  virtual ~BasicShadowImageLayer()
+  {
+    MOZ_COUNT_DTOR(BasicShadowImageLayer);
+  }
+
+  virtual PRBool Init(gfxSharedImageSurface* front, const nsIntSize& size)
+  { return PR_TRUE; }
+
+  virtual already_AddRefed<gfxSharedImageSurface>
+  Swap(gfxSharedImageSurface* newFront)
+  { return NULL; }
+
+  virtual void Paint(gfxContext* aContext,
+                     LayerManager::DrawThebesLayerCallback aCallback,
+                     void* aCallbackData,
+                     float aOpacity)
+  {}
+
+  MOZ_LAYER_DECL_NAME("BasicShadowImageLayer", TYPE_SHADOW)
+};
+
+class BasicShadowCanvasLayer : public ShadowCanvasLayer,
+                               BasicImplData
+{
+public:
+  BasicShadowCanvasLayer(BasicShadowLayerManager* aLayerManager) :
+    ShadowCanvasLayer(aLayerManager, static_cast<BasicImplData*>(this))
+  {
+    MOZ_COUNT_CTOR(BasicShadowCanvasLayer);
+  }
+  virtual ~BasicShadowCanvasLayer()
+  {
+    MOZ_COUNT_DTOR(BasicShadowCanvasLayer);
+  }
+
+  virtual void Initialize(const Data& aData)
+  {}
+
+  virtual void Updated(const nsIntRect& aRect)
+  {}
+
+  virtual already_AddRefed<gfxSharedImageSurface>
+  Swap(gfxSharedImageSurface* newFront)
+  { return NULL; }
+
+  virtual void Paint(gfxContext* aContext,
+                     LayerManager::DrawThebesLayerCallback aCallback,
+                     void* aCallbackData,
+                     float aOpacity)
+  {}
+
+  MOZ_LAYER_DECL_NAME("BasicShadowCanvasLayer", TYPE_SHADOW)
+};
+
+// Create a shadow layer (PLayerChild) for aLayer, if we're forwarding
+// our layer tree to a parent process.  Record the new layer creation
+// in the current open transaction as a side effect.
+template<typename CreatedMethod>
+static void
+MaybeCreateShadowFor(BasicShadowableLayer* aLayer,
+                     BasicShadowLayerManager* aMgr,
+                     CreatedMethod aMethod)
+{
+  if (!aMgr->HasShadowManager()) {
+    return;
+  }
+
+  PLayerChild* shadow = aMgr->ConstructShadowFor(aLayer);
+  // XXX error handling
+  NS_ABORT_IF_FALSE(shadow, "failed to create shadow");
+
+  aLayer->SetShadow(shadow);
+  (aMgr->*aMethod)(aLayer);
+}
+#define MAYBE_CREATE_SHADOW(_type)                                      \
+  MaybeCreateShadowFor(layer, this,                                     \
+                       &ShadowLayerForwarder::Created ## _type ## Layer)
+
+already_AddRefed<ThebesLayer>
+BasicShadowLayerManager::CreateThebesLayer()
+{
+  NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
+  nsRefPtr<BasicShadowableThebesLayer> layer =
+    new BasicShadowableThebesLayer(this);
+  MAYBE_CREATE_SHADOW(Thebes);
+  return layer.forget();
+}
+
+already_AddRefed<ContainerLayer>
+BasicShadowLayerManager::CreateContainerLayer()
+{
+  NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
+  nsRefPtr<BasicShadowableContainerLayer> layer =
+    new BasicShadowableContainerLayer(this);
+  MAYBE_CREATE_SHADOW(Container);
+  return layer.forget();
+}
+
+already_AddRefed<ImageLayer>
+BasicShadowLayerManager::CreateImageLayer()
+{
+  NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
+  nsRefPtr<BasicShadowableImageLayer> layer =
+    new BasicShadowableImageLayer(this);
+  MAYBE_CREATE_SHADOW(Image);
+  return layer.forget();
+}
+
+already_AddRefed<ColorLayer>
+BasicShadowLayerManager::CreateColorLayer()
+{
+  NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
+  nsRefPtr<BasicShadowableColorLayer> layer =
+    new BasicShadowableColorLayer(this);
+  MAYBE_CREATE_SHADOW(Color);
+  return layer.forget();
+}
+
+already_AddRefed<CanvasLayer>
+BasicShadowLayerManager::CreateCanvasLayer()
+{
+  NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
+  nsRefPtr<BasicShadowableCanvasLayer> layer =
+    new BasicShadowableCanvasLayer(this);
+  MAYBE_CREATE_SHADOW(Canvas);
+  return layer.forget();
+}
+already_AddRefed<ShadowThebesLayer>
+BasicShadowLayerManager::CreateShadowThebesLayer()
+{
+  NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
+  nsRefPtr<ShadowThebesLayer> layer = new BasicShadowThebesLayer(this);
+  return layer.forget();
+}
+
+already_AddRefed<ShadowImageLayer>
+BasicShadowLayerManager::CreateShadowImageLayer()
+{
+  NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
+  nsRefPtr<ShadowImageLayer> layer = new BasicShadowImageLayer(this);
+  return layer.forget();
+}
+
+already_AddRefed<ShadowCanvasLayer>
+BasicShadowLayerManager::CreateShadowCanvasLayer()
+{
+  NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
+  nsRefPtr<ShadowCanvasLayer> layer = new BasicShadowCanvasLayer(this);
+  return layer.forget();
+}
+
+BasicShadowLayerManager::BasicShadowLayerManager(nsIWidget* aWidget) :
+  BasicLayerManager(aWidget)
+{
+  MOZ_COUNT_CTOR(BasicShadowLayerManager);
+}
+
+BasicShadowLayerManager::~BasicShadowLayerManager()
+{
+  // FIXME/bug 570294: shadow forwarders don't have __delete__ until
+  // they have manager protocols
+  //
+  //if (HasShadowManager())
+  //  PLayersChild::Send__delete__(mShadow);
+  MOZ_COUNT_DTOR(BasicShadowLayerManager);
+}
+
+void
+BasicShadowLayerManager::SetRoot(Layer* aLayer)
+{
+  if (mRoot != aLayer) {
+    if (HasShadowManager()) {
+      ShadowLayerForwarder::SetRoot(Hold(aLayer));
+    }
+    BasicLayerManager::SetRoot(aLayer);
+  }
+}
+
+void
+BasicShadowLayerManager::Mutated(Layer* aLayer)
+{
+  NS_ASSERTION(InConstruction() || InDrawing(), "wrong phase");
+  if (HasShadowManager()) {
+    ShadowLayerForwarder::Mutated(Hold(aLayer));
+  }
+}
+
+void
+BasicShadowLayerManager::BeginTransactionWithTarget(gfxContext* aTarget)
+{
+  NS_ABORT_IF_FALSE(mKeepAlive.IsEmpty(), "uncommitted txn?");
+  if (HasShadowManager()) {
+    ShadowLayerForwarder::BeginTransaction();
+  }
+  BasicLayerManager::BeginTransactionWithTarget(aTarget);
+}
+
+void
+BasicShadowLayerManager::EndTransaction(DrawThebesLayerCallback aCallback,
+                                        void* aCallbackData)
+{
+  BasicLayerManager::EndTransaction(aCallback, aCallbackData);
+#ifdef DEBUG
+  mPhase = PHASE_FORWARD;
+#endif
+
+  // forward this transaction's changeset to our ShadowLayerManager
+  nsAutoTArray<EditReply, 10> replies;
+  if (HasShadowManager() && !ShadowLayerForwarder::EndTransaction(&replies)) {
+    NS_WARNING("failed to forward Layers transaction");
+  }
+
+  // this may result in Layers being deleted, which results in
+  // PLayer::Send__delete__()
+  mKeepAlive.Clear();
+
+#ifdef DEBUG
+  mPhase = PHASE_NONE;
+#endif
+}
+
+ShadowableLayer*
+BasicShadowLayerManager::Hold(Layer* aLayer)
+{
+  NS_ABORT_IF_FALSE(HasShadowManager(),
+                    "top-level tree, no shadow tree to remote to");
+
+  ShadowableLayer* shadowable = ToShadowable(aLayer);
+  NS_ABORT_IF_FALSE(shadowable, "trying to remote an unshadowable layer");
+
+  mKeepAlive.AppendElement(aLayer);
+  return shadowable;
+}
+#endif  // MOZ_IPC
+
 }
 }
--- a/gfx/layers/basic/BasicLayers.h
+++ b/gfx/layers/basic/BasicLayers.h
@@ -1,9 +1,9 @@
-/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  * ***** 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/
  *
@@ -40,30 +40,45 @@
 
 #include "Layers.h"
 
 #include "gfxContext.h"
 #include "gfxCachedTempSurface.h"
 #include "nsAutoRef.h"
 #include "nsThreadUtils.h"
 
+#ifdef MOZ_IPC
+#include "mozilla/layers/ShadowLayers.h"
+#endif
+
 class nsIWidget;
 
 namespace mozilla {
 namespace layers {
 
+class BasicShadowableLayer;
+class ShadowThebesLayer;
+class ShadowImageLayer;
+class ShadowCanvasLayer;
+
 /**
  * This is a cairo/Thebes-only, main-thread-only implementation of layers.
  * 
  * In each transaction, the client sets up the layer tree and then during
  * the drawing phase, each ThebesLayer is painted directly into the target
  * context (with appropriate clipping and Push/PopGroups performed
  * between layers).
  */
-class THEBES_API BasicLayerManager : public LayerManager {
+class THEBES_API BasicLayerManager :
+#ifdef MOZ_IPC
+    public ShadowLayerManager
+#else
+    public LayerManager
+#endif
+{
 public:
   /**
    * Construct a BasicLayerManager which will have no default
    * target context. SetDefaultTarget or BeginTransactionWithTarget
    * must be called for any rendering to happen. ThebesLayers will not
    * be retained.
    */
   BasicLayerManager();
@@ -114,29 +129,46 @@ public:
   virtual void SetRoot(Layer* aLayer);
 
   virtual already_AddRefed<ThebesLayer> CreateThebesLayer();
   virtual already_AddRefed<ContainerLayer> CreateContainerLayer();
   virtual already_AddRefed<ImageLayer> CreateImageLayer();
   virtual already_AddRefed<CanvasLayer> CreateCanvasLayer();
   virtual already_AddRefed<ImageContainer> CreateImageContainer();
   virtual already_AddRefed<ColorLayer> CreateColorLayer();
+  virtual already_AddRefed<ShadowThebesLayer> CreateShadowThebesLayer()
+  { return NULL; }
+  virtual already_AddRefed<ShadowImageLayer> CreateShadowImageLayer()
+  { return NULL; }
+  virtual already_AddRefed<ShadowCanvasLayer> CreateShadowCanvasLayer()
+  { return NULL; }
+
   virtual LayersBackend GetBackendType() { return LAYERS_BASIC; }
 
 #ifdef DEBUG
   PRBool InConstruction() { return mPhase == PHASE_CONSTRUCTION; }
   PRBool InDrawing() { return mPhase == PHASE_DRAWING; }
+  PRBool InForward() { return mPhase == PHASE_FORWARD; }
   PRBool InTransaction() { return mPhase != PHASE_NONE; }
 #endif
   gfxContext* GetTarget() { return mTarget; }
   PRBool IsRetained() { return mWidget != nsnull; }
 
 #ifdef MOZ_LAYERS_HAVE_LOG
   virtual const char* Name() const { return "Basic"; }
 #endif // MOZ_LAYERS_HAVE_LOG
+
+protected:
+#ifdef DEBUG
+  enum TransactionPhase {
+    PHASE_NONE, PHASE_CONSTRUCTION, PHASE_DRAWING, PHASE_FORWARD
+  };
+  TransactionPhase mPhase;
+#endif
+
 private:
   // Paints aLayer to mTarget.
   void PaintLayer(Layer* aLayer,
                   DrawThebesLayerCallback aCallback,
                   void* aCallbackData,
                   float aOpacity);
 
   already_AddRefed<gfxContext> PushGroupWithCachedSurface(gfxContext *aTarget,
@@ -151,24 +183,56 @@ private:
   // The default context for BeginTransaction.
   nsRefPtr<gfxContext> mDefaultTarget;
   // The context to draw into.
   nsRefPtr<gfxContext> mTarget;
 
   // Cached surface for double buffering
   gfxCachedTempSurface mCachedSurface;
 
-#ifdef DEBUG
-  enum TransactionPhase { PHASE_NONE, PHASE_CONSTRUCTION, PHASE_DRAWING };
-  TransactionPhase mPhase;
-#endif
-
   BufferMode   mDoubleBuffering;
   PRPackedBool mUsingDefaultTarget;
 };
+ 
+
+#ifdef MOZ_IPC
+class BasicShadowLayerManager : public BasicLayerManager,
+                                public ShadowLayerForwarder
+{
+  typedef nsTArray<nsRefPtr<Layer> > LayerRefArray;
+
+public:
+  BasicShadowLayerManager(nsIWidget* aWidget);
+  virtual ~BasicShadowLayerManager();
+
+  virtual void BeginTransactionWithTarget(gfxContext* aTarget);
+  virtual void EndTransaction(DrawThebesLayerCallback aCallback,
+                              void* aCallbackData);
+
+  virtual void SetRoot(Layer* aLayer);
+
+  virtual void Mutated(Layer* aLayer);
+
+  virtual already_AddRefed<ThebesLayer> CreateThebesLayer();
+  virtual already_AddRefed<ContainerLayer> CreateContainerLayer();
+  virtual already_AddRefed<ImageLayer> CreateImageLayer();
+  virtual already_AddRefed<CanvasLayer> CreateCanvasLayer();
+  virtual already_AddRefed<ColorLayer> CreateColorLayer();
+  virtual already_AddRefed<ShadowThebesLayer> CreateShadowThebesLayer();
+  virtual already_AddRefed<ShadowImageLayer> CreateShadowImageLayer();
+  virtual already_AddRefed<ShadowCanvasLayer> CreateShadowCanvasLayer();
+
+  virtual const char* Name() const { return "BasicShadowLayerManager"; }
+
+  ShadowableLayer* Hold(Layer* aLayer);
+
+private:
+  LayerRefArray mKeepAlive;
+};
+#endif  // MOZ_IPC
 
 }
 }
 
 /**
  * We need to be able to hold a reference to a gfxASurface from Image
  * subclasses. This is potentially a problem since Images can be addrefed
  * or released off the main thread. We can ensure that we never AddRef