Bug 648484, parts 3, 3.1, and 3.2: Allow passing a "backend hint" to GetLayerManager() to request a non-default layer manager backend. Deal with failure to hook up shadow layers. sr=roc
authorChris Jones <jones.chris.g@gmail.com>
Tue, 09 Aug 2011 12:38:26 -0700
changeset 75249 8c6c251baaec5f0c01fe2221e0230c17032e290c
parent 75248 32c611f5507777b5af0e022145b2746ab6f09826
child 75250 d04af79b34ae49286c60bf6b35db0ada7daa07f4
push idunknown
push userunknown
push dateunknown
reviewersroc
bugs648484
milestone8.0a1
Bug 648484, parts 3, 3.1, and 3.2: Allow passing a "backend hint" to GetLayerManager() to request a non-default layer manager backend. Deal with failure to hook up shadow layers. sr=roc
dom/ipc/TabChild.cpp
dom/ipc/TabParent.cpp
gfx/layers/ipc/PLayers.ipdl
gfx/layers/ipc/ShadowLayers.cpp
gfx/layers/ipc/ShadowLayers.h
ipc/glue/IPCMessageUtils.h
layout/ipc/PRenderFrame.ipdl
layout/ipc/RenderFrameChild.cpp
layout/ipc/RenderFrameChild.h
layout/ipc/RenderFrameParent.cpp
layout/ipc/RenderFrameParent.h
widget/public/nsIWidget.h
widget/src/cocoa/nsCocoaWindow.h
widget/src/cocoa/nsCocoaWindow.mm
widget/src/windows/nsWindow.cpp
widget/src/windows/nsWindow.h
widget/src/xpwidgets/PuppetWidget.cpp
widget/src/xpwidgets/PuppetWidget.h
widget/src/xpwidgets/nsBaseWidget.cpp
widget/src/xpwidgets/nsBaseWidget.h
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -466,68 +466,76 @@ TabChild::DestroyWindow()
         mRemoteFrame->Destroy();
         mRemoteFrame = nsnull;
     }
 }
 
 void
 TabChild::ActorDestroy(ActorDestroyReason why)
 {
-  // The messageManager relays messages via the TabChild which
-  // no longer exists.
-  static_cast<nsFrameMessageManager*>
-    (mTabChildGlobal->mMessageManager.get())->Disconnect();
-  mTabChildGlobal->mMessageManager = nsnull;
+  if (mTabChildGlobal) {
+    // The messageManager relays messages via the TabChild which
+    // no longer exists.
+    static_cast<nsFrameMessageManager*>
+      (mTabChildGlobal->mMessageManager.get())->Disconnect();
+    mTabChildGlobal->mMessageManager = nsnull;
+  }
 }
 
 TabChild::~TabChild()
 {
     nsCOMPtr<nsIWebBrowser> webBrowser = do_QueryInterface(mWebNav);
     if (webBrowser) {
       webBrowser->SetContainerWindow(nsnull);
     }
     if (mCx) {
       DestroyCx();
     }
     
-    nsEventListenerManager* elm = mTabChildGlobal->GetListenerManager(PR_FALSE);
-    if (elm) {
-      elm->Disconnect();
+    if (mTabChildGlobal) {
+      nsEventListenerManager* elm = mTabChildGlobal->GetListenerManager(PR_FALSE);
+      if (elm) {
+        elm->Disconnect();
+      }
+      mTabChildGlobal->mTabChild = nsnull;
     }
-    mTabChildGlobal->mTabChild = nsnull;
 }
 
 bool
 TabChild::RecvLoadURL(const nsCString& uri)
 {
     printf("loading %s, %d\n", uri.get(), NS_IsMainThread());
 
     nsresult rv = mWebNav->LoadURI(NS_ConvertUTF8toUTF16(uri).get(),
                                    nsIWebNavigation::LOAD_FLAGS_NONE,
                                    NULL, NULL, NULL);
     if (NS_FAILED(rv)) {
         NS_WARNING("mWebNav->LoadURI failed. Eating exception, what else can I do?");
     }
 
-    return NS_SUCCEEDED(rv);
+    return true;
 }
 
 bool
 TabChild::RecvShow(const nsIntSize& size)
 {
     printf("[TabChild] SHOW (w,h)= (%d, %d)\n", size.width, size.height);
 
     nsCOMPtr<nsIBaseWindow> baseWindow = do_QueryInterface(mWebNav);
     if (!baseWindow) {
         NS_ERROR("mWebNav doesn't QI to nsIBaseWindow");
         return false;
     }
 
     if (!InitWidget(size)) {
-        return false;
+        // We can fail to initialize our widget if the <browser
+        // remote> has already been destroyed, and we couldn't hook
+        // into the parent-process's layer system.  That's not a fatal
+        // error.
+        return true;
     }
 
     baseWindow->InitWindow(0, mWidget,
                            0, 0, size.width, size.height);
     baseWindow->Create();
     baseWindow->SetVisibility(PR_TRUE);
 
     // IPC uses a WebBrowser object for which DNS prefetching is turned off
@@ -546,16 +554,20 @@ TabChild::RecvShow(const nsIntSize& size
 
 bool
 TabChild::RecvUpdateDimensions(const nsRect& rect, const nsIntSize& size)
 {
 #ifdef DEBUG
     printf("[TabChild] Update Dimensions to (x,y,w,h)= (%ud, %ud, %ud, %ud) and move to (w,h)= (%ud, %ud)\n", rect.x, rect.y, rect.width, rect.height, size.width, size.height);
 #endif
 
+    if (!mRemoteFrame) {
+        return true;
+    }
+
     mOuterRect.x = rect.x;
     mOuterRect.y = rect.y;
     mOuterRect.width = rect.width;
     mOuterRect.height = rect.height;
 
     mWidget->Resize(0, 0, size.width, size.height,
                     PR_TRUE);
 
@@ -789,17 +801,19 @@ TabChild::DeallocPOfflineCacheUpdate(POf
   delete offlineCacheUpdate;
   return true;
 }
 
 bool
 TabChild::RecvLoadRemoteScript(const nsString& aURL)
 {
   if (!mCx && !InitTabChildGlobal())
-    return false;
+    // This can happen if we're half-destroyed.  It's not a fatal
+    // error.
+    return true;
 
   LoadFrameScriptInternal(aURL);
   return true;
 }
 
 bool
 TabChild::RecvAsyncMessage(const nsString& aMessage,
                            const nsString& aJSON)
@@ -839,20 +853,22 @@ public:
 
   nsRefPtr<TabChild> mTabChild;
   TabChildGlobal* mTabChildGlobal;
 };
 
 bool
 TabChild::RecvDestroy()
 {
-  // Let the frame scripts know the child is being closed
-  nsContentUtils::AddScriptRunner(
-    new UnloadScriptEvent(this, mTabChildGlobal)
-  );
+  if (mTabChildGlobal) {
+    // Let the frame scripts know the child is being closed
+    nsContentUtils::AddScriptRunner(
+      new UnloadScriptEvent(this, mTabChildGlobal)
+    );
+  }
 
   // XXX what other code in ~TabChild() should we be running here?
   DestroyWindow();
 
   return Send__delete__(this);
 }
 
 PRenderFrameChild*
@@ -960,32 +976,30 @@ TabChild::InitWidget(const nsIntSize& si
         static_cast<RenderFrameChild*>(SendPRenderFrameConstructor());
     if (!remoteFrame) {
       NS_WARNING("failed to construct RenderFrame");
       return false;
     }
 
     NS_ABORT_IF_FALSE(0 == remoteFrame->ManagedPLayersChild().Length(),
                       "shouldn't have a shadow manager yet");
-    PLayersChild* shadowManager = remoteFrame->SendPLayersConstructor();
+    LayerManager::LayersBackend be;
+    PLayersChild* shadowManager = remoteFrame->SendPLayersConstructor(&be);
     if (!shadowManager) {
       NS_WARNING("failed to construct LayersChild");
       // This results in |remoteFrame| being deleted.
       PRenderFrameChild::Send__delete__(remoteFrame);
       return false;
     }
 
-    LayerManager* lm = mWidget->GetLayerManager();
-    NS_ABORT_IF_FALSE(LayerManager::LAYERS_BASIC == lm->GetBackendType(),
-                      "content processes should only be using BasicLayers");
-
-    BasicShadowLayerManager* bslm = static_cast<BasicShadowLayerManager*>(lm);
-    NS_ABORT_IF_FALSE(!bslm->HasShadowManager(),
-                      "PuppetWidget shouldn't have shadow manager yet");
-    bslm->SetShadowManager(shadowManager);
+    ShadowLayerForwarder* lf =
+        mWidget->GetLayerManager(shadowManager, be)->AsShadowForwarder();
+    NS_ABORT_IF_FALSE(lf && lf->HasShadowManager(),
+                      "PuppetWidget should have shadow manager");
+    lf->SetParentBackendType(be);
 
     mRemoteFrame = remoteFrame;
     return true;
 }
 
 static bool
 SendSyncMessageToParent(void* aCallbackData,
                         const nsAString& aMessage,
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -763,18 +763,17 @@ TabParent::HandleDelayedDialogs()
                                          PR_TRUE, PR_TRUE);
   }
 }
 
 PRenderFrameParent*
 TabParent::AllocPRenderFrame()
 {
   nsRefPtr<nsFrameLoader> frameLoader = GetFrameLoader();
-  NS_WARN_IF_FALSE(frameLoader, "'message sent to unknown actor ID' coming up");
-  return frameLoader ? new RenderFrameParent(frameLoader) : nsnull;
+  return new RenderFrameParent(frameLoader);
 }
 
 bool
 TabParent::DeallocPRenderFrame(PRenderFrameParent* aFrame)
 {
   delete aFrame;
   return true;
 }
--- a/gfx/layers/ipc/PLayers.ipdl
+++ b/gfx/layers/ipc/PLayers.ipdl
@@ -49,17 +49,16 @@ using gfxRGBA;
 using nsIntPoint;
 using nsIntRect;
 using nsIntRegion;
 using nsIntSize;
 using mozilla::GraphicsFilterType;
 using mozilla::layers::FrameMetrics;
 using mozilla::layers::SurfaceDescriptorX11;
 using mozilla::null_t;
-using mozilla::LayersBackend;
 
 /**
  * The layers protocol is spoken between thread contexts that manage
  * layer (sub)trees.  The protocol comprises atomically publishing
  * layer subtrees to a "shadow" thread context (which grafts the
  * subtree into its own tree), and atomically updating a published
  * subtree.  ("Atomic" in this sense is wrt painting.)
  */
@@ -251,16 +250,13 @@ sync protocol PLayers {
   manages PLayer;
 
 parent:
   async PLayer();
 
   sync Update(Edit[] cset)
     returns (EditReply[] reply);
 
-  sync GetParentType()
-    returns (LayersBackend backend);
-
   async __delete__();
 };
 
 } // namespace layers
 } // namespace mozilla
--- a/gfx/layers/ipc/ShadowLayers.cpp
+++ b/gfx/layers/ipc/ShadowLayers.cpp
@@ -374,28 +374,16 @@ ShadowLayerForwarder::EndTransaction(Inf
     MOZ_LAYERS_LOG(("[LayersForwarder] WARNING: sending transaction failed!"));
     return PR_FALSE;
   }
 
   MOZ_LAYERS_LOG(("[LayersForwarder] ... done"));
   return PR_TRUE;
 }
 
-LayersBackend
-ShadowLayerForwarder::GetParentBackendType()
-{
-  if (mParentBackend == LayerManager::LAYERS_NONE) {
-    LayersBackend backend;
-    if (mShadowManager->SendGetParentType(&backend)) {
-      mParentBackend = backend;
-    }
-  }
-  return mParentBackend;
-}
-
 static gfxASurface::gfxImageFormat
 OptimalFormatFor(gfxASurface::gfxContentType aContent)
 {
   switch (aContent) {
   case gfxASurface::CONTENT_COLOR:
 #ifdef MOZ_GFX_OPTIMIZE_MOBILE
     return gfxASurface::ImageFormatRGB16_565;
 #else
--- a/gfx/layers/ipc/ShadowLayers.h
+++ b/gfx/layers/ipc/ShadowLayers.h
@@ -240,16 +240,21 @@ public:
   /**
    * Set an actor through which layer updates will be pushed.
    */
   void SetShadowManager(PLayersChild* aShadowManager)
   {
     mShadowManager = aShadowManager;
   }
 
+  void SetParentBackendType(LayersBackend aBackendType)
+  {
+    mParentBackend = aBackendType;
+  }
+
   /**
    * True if this is forwarding to a ShadowLayerManager.
    */
   PRBool HasShadowManager() const { return !!mShadowManager; }
   PLayersChild* GetShadowManager() const { return mShadowManager; }
 
   /**
    * The following Alloc/Open/Destroy interfaces abstract over the
@@ -320,17 +325,20 @@ public:
   void DestroySharedSurface(SurfaceDescriptor* aSurface);
 
   /**
    * Construct a shadow of |aLayer| on the "other side", at the
    * ShadowLayerManager.
    */
   PLayerChild* ConstructShadowFor(ShadowableLayer* aLayer);
 
-  LayersBackend GetParentBackendType();
+  LayersBackend GetParentBackendType()
+  {
+    return mParentBackend;
+  }
 
   /*
    * No need to use double buffer in system memory with GPU rendering,
    * texture used as front buffer.
    */
   bool ShouldDoubleBuffer() { return GetParentBackendType() == LayerManager::LAYERS_BASIC; }
 
 protected:
--- a/ipc/glue/IPCMessageUtils.h
+++ b/ipc/glue/IPCMessageUtils.h
@@ -511,31 +511,31 @@ struct ParamTraits<mozilla::gfxSurfaceTy
 
 template<>
 struct ParamTraits<mozilla::LayersBackend>
 {
   typedef mozilla::LayersBackend paramType;
 
   static void Write(Message* msg, const paramType& param)
   {
-    if (LayerManager::LAYERS_NONE < param &&
+    if (LayerManager::LAYERS_NONE <= param &&
         param < LayerManager::LAYERS_LAST) {
       WriteParam(msg, int32(param));
       return;
     }
-    NS_RUNTIMEABORT("surface type not reached");
+    NS_RUNTIMEABORT("backend type not reached");
   }
 
   static bool Read(const Message* msg, void** iter, paramType* result)
   {
     int32 type;
     if (!ReadParam(msg, iter, &type))
       return false;
 
-    if (LayerManager::LAYERS_NONE < type &&
+    if (LayerManager::LAYERS_NONE <= type &&
         type < LayerManager::LAYERS_LAST) {
       *result = paramType(type);
       return true;
     }
     return false;
   }
 };
 
--- a/layout/ipc/PRenderFrame.ipdl
+++ b/layout/ipc/PRenderFrame.ipdl
@@ -36,16 +36,18 @@
  * 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 protocol PBrowser;
 include protocol PLayers;
 
+using mozilla::LayersBackend;
+
 namespace mozilla {
 namespace layout {
 
 /**
  * PRenderFrame (in the layout sense of "frame") represents one web
  * "page".  It's used to graft content processes' layer trees into
  * chrome's rendering path.  The lifetime of a PRenderFrame is tied to
  * its PresShell in the child process.
@@ -54,17 +56,19 @@ namespace layout {
  * only makes sense wrt documents loaded by the child.
  */
 sync protocol PRenderFrame
 {
     manager PBrowser;
     manages PLayers;
 
 parent:
-    async PLayers();
+    sync PLayers()
+      returns (LayersBackend backend);
+
     async __delete__();
 
 state EMPTY:
     recv PLayers goto HAVE_CONTENT;
 state HAVE_CONTENT:
     recv __delete__;
 };
 
--- a/layout/ipc/RenderFrameChild.cpp
+++ b/layout/ipc/RenderFrameChild.cpp
@@ -61,17 +61,17 @@ RenderFrameChild::Destroy()
     // |layers| was just deleted, take care
   }
 
   Send__delete__(this);
   // WARNING: |this| is dead, hands off
 }
 
 PLayersChild*
-RenderFrameChild::AllocPLayers()
+RenderFrameChild::AllocPLayers(LayerManager::LayersBackend* aBackendType)
 {
   return new ShadowLayersChild();
 }
 
 bool
 RenderFrameChild::DeallocPLayers(PLayersChild* aLayers)
 {
   delete aLayers;
--- a/layout/ipc/RenderFrameChild.h
+++ b/layout/ipc/RenderFrameChild.h
@@ -51,17 +51,17 @@ class RenderFrameChild : public PRenderF
 public:
   RenderFrameChild() {}
   virtual ~RenderFrameChild() {}
 
   void Destroy();
 
 protected:
   NS_OVERRIDE
-  virtual PLayersChild* AllocPLayers();
+  virtual PLayersChild* AllocPLayers(LayerManager::LayersBackend* aBackendType);
   NS_OVERRIDE
   virtual bool DeallocPLayers(PLayersChild* aLayers);
 };
 
 } // namespace layout
 } // namespace mozilla
 
 #endif  // mozilla_dom_RenderFrameChild_h
--- a/layout/ipc/RenderFrameParent.cpp
+++ b/layout/ipc/RenderFrameParent.cpp
@@ -560,19 +560,20 @@ BuildBackgroundPatternFor(ContainerLayer
   layer->SetVisibleRegion(bgRgn);
 
   aContainer->InsertAfter(layer, nsnull);
 }
 
 RenderFrameParent::RenderFrameParent(nsFrameLoader* aFrameLoader)
   : mFrameLoader(aFrameLoader)
 {
-  NS_ABORT_IF_FALSE(aFrameLoader, "Need a frameloader here");
-  mContentViews[FrameMetrics::ROOT_SCROLL_ID] =
-    new nsContentView(aFrameLoader, FrameMetrics::ROOT_SCROLL_ID);
+  if (aFrameLoader) {
+    mContentViews[FrameMetrics::ROOT_SCROLL_ID] =
+      new nsContentView(aFrameLoader, FrameMetrics::ROOT_SCROLL_ID);
+  }
 }
 
 RenderFrameParent::~RenderFrameParent()
 {}
 
 void
 RenderFrameParent::Destroy()
 {
@@ -703,49 +704,55 @@ RenderFrameParent::OwnerContentChanged(n
   NS_ABORT_IF_FALSE(mFrameLoader->GetOwnerContent() == aContent,
                     "Don't build new map if owner is same!");
   BuildViewMap();
 }
 
 void
 RenderFrameParent::ActorDestroy(ActorDestroyReason why)
 {
-  if (mFrameLoader->GetCurrentRemoteFrame() == this) {
+  if (mFrameLoader && mFrameLoader->GetCurrentRemoteFrame() == this) {
     // XXX this might cause some weird issues ... we'll just not
     // redraw the part of the window covered by this until the "next"
     // remote frame has a layer-tree transaction.  For
     // why==NormalShutdown, we'll definitely want to do something
     // better, especially as nothing guarantees another Update() from
     // the "next" remote layer tree.
     mFrameLoader->SetCurrentRemoteFrame(nsnull);
   }
   mFrameLoader = nsnull;
 }
 
 PLayersParent*
-RenderFrameParent::AllocPLayers()
+RenderFrameParent::AllocPLayers(LayerManager::LayersBackend* aBackendType)
 {
+  if (!mFrameLoader) {
+    *aBackendType = LayerManager::LAYERS_NONE;
+    return nsnull;
+  }
+
   LayerManager* lm = GetLayerManager();
-  switch (lm->GetBackendType()) {
+  switch (*aBackendType = lm->GetBackendType()) {
   case LayerManager::LAYERS_BASIC: {
     BasicShadowLayerManager* bslm = static_cast<BasicShadowLayerManager*>(lm);
     return new ShadowLayersParent(bslm);
   }
   case LayerManager::LAYERS_OPENGL: {
     LayerManagerOGL* lmo = static_cast<LayerManagerOGL*>(lm);
     return new ShadowLayersParent(lmo);
   }
 #ifdef MOZ_ENABLE_D3D9_LAYER
   case LayerManager::LAYERS_D3D9: {
     LayerManagerD3D9* lmd3d9 = static_cast<LayerManagerD3D9*>(lm);
     return new ShadowLayersParent(lmd3d9);
   }
 #endif //MOZ_ENABLE_D3D9_LAYER
   default: {
     NS_WARNING("shadow layers no sprechen D3D backend yet");
+    *aBackendType = LayerManager::LAYERS_NONE;
     return nsnull;
   }
   }
 }
 
 bool
 RenderFrameParent::DeallocPLayers(PLayersParent* aLayers)
 {
--- a/layout/ipc/RenderFrameParent.h
+++ b/layout/ipc/RenderFrameParent.h
@@ -96,17 +96,17 @@ public:
                                      LayerManager* aManager,
                                      const nsIntRect& aVisibleRect);
 
   void OwnerContentChanged(nsIContent* aContent);
 
 protected:
   NS_OVERRIDE void ActorDestroy(ActorDestroyReason why);
 
-  NS_OVERRIDE virtual PLayersParent* AllocPLayers();
+  NS_OVERRIDE virtual PLayersParent* AllocPLayers(LayerManager::LayersBackend* aBackendType);
   NS_OVERRIDE virtual bool DeallocPLayers(PLayersParent* aLayers);
 
 private:
   void BuildViewMap();
 
   LayerManager* GetLayerManager() const;
   ShadowLayersParent* GetShadowLayers() const;
   ContainerLayer* GetRootLayer() const;
--- a/widget/public/nsIWidget.h
+++ b/widget/public/nsIWidget.h
@@ -42,16 +42,17 @@
 #include "nsColor.h"
 #include "nsCoord.h"
 #include "nsRect.h"
 #include "nsPoint.h"
 #include "nsRegion.h"
 #include "nsStringGlue.h"
 
 #include "prthread.h"
+#include "Layers.h"
 #include "nsEvent.h"
 #include "nsCOMPtr.h"
 #include "nsITheme.h"
 #include "nsNativeWidget.h"
 #include "nsWidgetInitData.h"
 #include "nsTArray.h"
 #include "nsXULAppAPI.h"
 
@@ -66,22 +67,22 @@ class   nsIRollupListener;
 class   nsIMenuRollup;
 class   nsGUIEvent;
 class   imgIContainer;
 class   gfxASurface;
 class   nsIContent;
 class   ViewWrapper;
 
 namespace mozilla {
-namespace layers {
-class LayerManager;
-}
 namespace dom {
 class PBrowserChild;
 }
+namespace layers {
+class PLayersChild;
+}
 }
 
 /**
  * Callback function that processes events.
  *
  * The argument is actually a subtype (subclass) of nsEvent which carries
  * platform specific information about the event. Platform specific code
  * knows how to deal with it.
@@ -112,18 +113,18 @@ typedef nsEventStatus (* EVENT_CALLBACK)
 #endif
 #ifdef XP_WIN
 #define NS_NATIVE_TSF_THREAD_MGR       100
 #define NS_NATIVE_TSF_CATEGORY_MGR     101
 #define NS_NATIVE_TSF_DISPLAY_ATTR_MGR 102
 #endif
 
 #define NS_IWIDGET_IID \
-  { 0xac809e35, 0x632c, 0x448d, \
-    { 0x9e, 0x34, 0x11, 0x62, 0x32, 0x60, 0x5e, 0xe6 } }
+  { 0xf43254ce, 0xd315, 0x458b, \
+    { 0xba, 0x72, 0xa8, 0xdf, 0x21, 0xcf, 0xa7, 0x2a } }
 
 /*
  * Window shadow styles
  * Also used for the -moz-window-shadow CSS property
  */
 
 #define NS_STYLE_WINDOW_SHADOW_NONE             0
 #define NS_STYLE_WINDOW_SHADOW_DEFAULT          1
@@ -269,16 +270,18 @@ struct IMEContext {
  * all basic and necessary functionality.
  */
 class nsIWidget : public nsISupports {
   protected:
     typedef mozilla::dom::PBrowserChild PBrowserChild;
 
   public:
     typedef mozilla::layers::LayerManager LayerManager;
+    typedef LayerManager::LayersBackend LayersBackend;
+    typedef mozilla::layers::PLayersChild PLayersChild;
 
     // Used in UpdateThemeGeometries.
     struct ThemeGeometry {
       // The -moz-appearance value for the themed widget
       PRUint8 mWidgetType;
       // The device-pixel rect within the window for the themed widget
       nsIntRect mRect;
 
@@ -889,36 +892,50 @@ class nsIWidget : public nsISupports {
      *
      * An AddRef has NOT been done for the caller.
      *
      * @return the toolkit this widget was created in. See nsToolkit.
      */
 
     virtual nsIToolkit* GetToolkit() = 0;    
 
+    enum LayerManagerPersistence
+    {
+      LAYER_MANAGER_CURRENT = 0,
+      LAYER_MANAGER_PERSISTENT
+    };
+
     /**
      * Return the widget's LayerManager. The layer tree for that
      * LayerManager is what gets rendered to the widget.
      *
      * @param aAllowRetaining an outparam that states whether the returned
      * layer manager should be used for retained layers
      */
     inline LayerManager* GetLayerManager(bool* aAllowRetaining = nsnull)
     {
-        return GetLayerManager(LAYER_MANAGER_CURRENT, aAllowRetaining);
+        return GetLayerManager(nsnull, LayerManager::LAYERS_NONE,
+                               LAYER_MANAGER_CURRENT, aAllowRetaining);
     }
 
-
-    enum LayerManagerPersistence
+    inline LayerManager* GetLayerManager(LayerManagerPersistence aPersistence,
+                                         bool* aAllowRetaining = nsnull)
     {
-      LAYER_MANAGER_CURRENT = 0,
-      LAYER_MANAGER_PERSISTENT
-    };
+        return GetLayerManager(nsnull, LayerManager::LAYERS_NONE,
+                               aPersistence, aAllowRetaining);
+    }
 
-    virtual LayerManager *GetLayerManager(LayerManagerPersistence aPersistence,
+    /**
+     * Like GetLayerManager(), but prefers creating a layer manager of
+     * type |aBackendHint| instead of what would normally be created.
+     * LAYERS_NONE means "no hint".
+     */
+    virtual LayerManager* GetLayerManager(PLayersChild* aShadowManager,
+                                          LayersBackend aBackendHint,
+                                          LayerManagerPersistence aPersistence = LAYER_MANAGER_CURRENT,
                                           bool* aAllowRetaining = nsnull) = 0;
 
     /**
      * Called after the LayerManager draws the layer tree
      *
      * @param aManager The drawing LayerManager.
      * @param aRect Current widget rect that is being drawn.
      */
--- a/widget/src/cocoa/nsCocoaWindow.h
+++ b/widget/src/cocoa/nsCocoaWindow.h
@@ -251,18 +251,19 @@ public:
     NS_IMETHOD              SetCursor(nsCursor aCursor);
     NS_IMETHOD              SetCursor(imgIContainer* aCursor, PRUint32 aHotspotX, PRUint32 aHotspotY);
 
     NS_IMETHOD              SetTitle(const nsAString& aTitle);
 
     NS_IMETHOD Invalidate(const nsIntRect &aRect, PRBool aIsSynchronous);
     NS_IMETHOD Update();
     virtual nsresult ConfigureChildren(const nsTArray<Configuration>& aConfigurations);
-    virtual LayerManager* GetLayerManager(bool *aAllowRetaining = nsnull);
-    virtual LayerManager* GetLayerManager(LayerManagerPersistence aPersistence = LAYER_MANAGER_CURRENT,
+    virtual LayerManager* GetLayerManager(PLayersChild* aShadowManager = nsnull,
+                                          LayersBackend aBackendHint = LayerManager::LAYERS_NONE,
+                                          LayerManagerPersistence aPersistence = LAYER_MANAGER_CURRENT,
                                           bool* aAllowRetaining = nsnull);
     NS_IMETHOD DispatchEvent(nsGUIEvent* event, nsEventStatus & aStatus) ;
     NS_IMETHOD CaptureRollupEvents(nsIRollupListener * aListener, nsIMenuRollup * aMenuRollup,
                                    PRBool aDoCapture, PRBool aConsumeRollupEvent);
     NS_IMETHOD GetAttention(PRInt32 aCycleCount);
     virtual PRBool HasPendingInputEvent();
     virtual nsTransparencyMode GetTransparencyMode();
     virtual void SetTransparencyMode(nsTransparencyMode aMode);
--- a/widget/src/cocoa/nsCocoaWindow.mm
+++ b/widget/src/cocoa/nsCocoaWindow.mm
@@ -926,29 +926,26 @@ nsCocoaWindow::ConfigureChildren(const n
 {
   if (mPopupContentView) {
     mPopupContentView->ConfigureChildren(aConfigurations);
   }
   return NS_OK;
 }
 
 LayerManager*
-nsCocoaWindow::GetLayerManager(bool *aAllowRetaining)
+nsCocoaWindow::GetLayerManager(PLayersChild* aShadowManager,
+                               LayersBackend aBackendHint,
+                               LayerManagerPersistence aPersistence,
+                               bool* aAllowRetaining)
 {
   if (mPopupContentView) {
-    return mPopupContentView->GetLayerManager(aAllowRetaining);
-  }
-  return nsnull;
-}
-
-LayerManager*
-nsCocoaWindow::GetLayerManager(LayerManagerPersistence, bool* aAllowRetaining)
-{
-  if (mPopupContentView) {
-    return mPopupContentView->GetLayerManager(aAllowRetaining);
+    return mPopupContentView->GetLayerManager(aShadowManager,
+                                              aBackendHint,
+                                              aPersistence,
+                                              aAllowRetaining);
   }
   return nsnull;
 }
 
 nsTransparencyMode nsCocoaWindow::GetTransparencyMode()
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
 
--- a/widget/src/windows/nsWindow.cpp
+++ b/widget/src/windows/nsWindow.cpp
@@ -3160,18 +3160,21 @@ GetLayerManagerPrefs(LayerManagerPrefs* 
   PRBool safeMode = PR_FALSE;
   nsCOMPtr<nsIXULRuntime> xr = do_GetService("@mozilla.org/xre/runtime;1");
   if (xr)
     xr->GetInSafeMode(&safeMode);
   aManagerPrefs->mDisableAcceleration =
     aManagerPrefs->mDisableAcceleration || safeMode;
 }
 
-mozilla::layers::LayerManager*
-nsWindow::GetLayerManager(LayerManagerPersistence aPersistence, bool* aAllowRetaining)
+LayerManager*
+nsWindow::GetLayerManager(PLayersChild* aShadowManager,
+                          LayersBackend aBackendHint,
+                          LayerManagerPersistence aPersistence,
+                          bool* aAllowRetaining)
 {
   if (aAllowRetaining) {
     *aAllowRetaining = true;
   }
 
 #ifdef MOZ_ENABLE_D3D10_LAYER
   if (mLayerManager) {
     if (mLayerManager->GetBackendType() ==
--- a/widget/src/windows/nsWindow.h
+++ b/widget/src/windows/nsWindow.h
@@ -154,17 +154,20 @@ public:
   virtual nsIntSize       ClientToWindowSize(const nsIntSize& aClientSize);
   NS_IMETHOD              DispatchEvent(nsGUIEvent* event, nsEventStatus & aStatus);
   NS_IMETHOD              EnableDragDrop(PRBool aEnable);
   NS_IMETHOD              CaptureMouse(PRBool aCapture);
   NS_IMETHOD              CaptureRollupEvents(nsIRollupListener * aListener, nsIMenuRollup * aMenuRollup,
                                               PRBool aDoCapture, PRBool aConsumeRollupEvent);
   NS_IMETHOD              GetAttention(PRInt32 aCycleCount);
   virtual PRBool          HasPendingInputEvent();
-  virtual LayerManager*   GetLayerManager(LayerManagerPersistence aPersistence = LAYER_MANAGER_CURRENT, bool* aAllowRetaining = nsnull);
+  virtual LayerManager*   GetLayerManager(PLayersChild* aShadowManager = nsnull,
+                                          LayersBackend aBackendHint = LayerManager::LAYERS_NONE,
+                                          LayerManagerPersistence aPersistence = LAYER_MANAGER_CURRENT,
+                                          bool* aAllowRetaining = nsnull);
   gfxASurface             *GetThebesSurface();
   NS_IMETHOD              OnDefaultButtonLoaded(const nsIntRect &aButtonRect);
   NS_IMETHOD              OverrideSystemMouseScrollSpeed(PRInt32 aOriginalDelta, PRBool aIsHorizontal, PRInt32 &aOverriddenDelta);
 
   virtual nsresult        SynthesizeNativeKeyEvent(PRInt32 aNativeKeyboardLayout,
                                                    PRInt32 aNativeKeyCode,
                                                    PRUint32 aModifierFlags,
                                                    const nsAString& aCharacters,
--- a/widget/src/xpwidgets/PuppetWidget.cpp
+++ b/widget/src/xpwidgets/PuppetWidget.cpp
@@ -325,20 +325,24 @@ PuppetWidget::DispatchEvent(nsGUIEvent* 
   if (event->message == NS_COMPOSITION_END) {
     mIMEComposing = PR_FALSE;
   }
 
   return NS_OK;
 }
 
 LayerManager*
-PuppetWidget::GetLayerManager(LayerManagerPersistence, bool* aAllowRetaining)
+PuppetWidget::GetLayerManager(PLayersChild* aShadowManager,
+                              LayersBackend aBackendHint,
+                              LayerManagerPersistence aPersistence,
+                              bool* aAllowRetaining)
 {
   if (!mLayerManager) {
     mLayerManager = new BasicShadowLayerManager(this);
+    mLayerManager->AsShadowForwarder()->SetShadowManager(aShadowManager);
   }
   if (aAllowRetaining) {
     *aAllowRetaining = true;
   }
   return mLayerManager;
 }
 
 gfxASurface*
--- a/widget/src/xpwidgets/PuppetWidget.h
+++ b/widget/src/xpwidgets/PuppetWidget.h
@@ -159,18 +159,21 @@ public:
                                  PRBool aDoCapture, PRBool aConsumeRollupEvent)
   { return NS_ERROR_UNEXPECTED; }
 
   //
   // nsBaseWidget methods we override
   //
 
 //NS_IMETHOD              CaptureMouse(PRBool aCapture);
-  virtual LayerManager*     GetLayerManager(LayerManagerPersistence aPersistence = LAYER_MANAGER_CURRENT,
-                                            bool* aAllowRetaining = nsnull);
+  virtual LayerManager*
+  GetLayerManager(PLayersChild* aShadowManager = nsnull,
+                  LayersBackend aBackendHint = LayerManager::LAYERS_NONE,
+                  LayerManagerPersistence aPersistence = LAYER_MANAGER_CURRENT,
+                  bool* aAllowRetaining = nsnull);
 //  virtual nsDeviceContext* GetDeviceContext();
   virtual gfxASurface*      GetThebesSurface();
 
   NS_IMETHOD ResetInputState();
   NS_IMETHOD SetIMEOpenState(PRBool aState);
   NS_IMETHOD GetIMEOpenState(PRBool *aState);
   NS_IMETHOD SetInputMode(const IMEContext& aContext);
   NS_IMETHOD GetInputMode(IMEContext& aContext);
--- a/widget/src/xpwidgets/nsBaseWidget.cpp
+++ b/widget/src/xpwidgets/nsBaseWidget.cpp
@@ -847,26 +847,27 @@ nsBaseWidget::GetShouldAccelerate()
 
   if (accelerateByDefault)
     return PR_TRUE;
 
   /* use the window acceleration flag */
   return mUseAcceleratedRendering;
 }
 
-LayerManager* nsBaseWidget::GetLayerManager(LayerManagerPersistence,
+LayerManager* nsBaseWidget::GetLayerManager(PLayersChild* aShadowManager,
+                                            LayersBackend aBackendHint,
+                                            LayerManagerPersistence aPersistence,
                                             bool* aAllowRetaining)
 {
   if (!mLayerManager) {
 
     mUseAcceleratedRendering = GetShouldAccelerate();
 
     if (mUseAcceleratedRendering) {
-      nsRefPtr<LayerManagerOGL> layerManager =
-        new mozilla::layers::LayerManagerOGL(this);
+      nsRefPtr<LayerManagerOGL> layerManager = new LayerManagerOGL(this);
       /**
        * XXX - On several OSes initialization is expected to fail for now.
        * If we'd get a none-basic layer manager they'd crash. This is ok though
        * since on those platforms it will fail. Anyone implementing new
        * platforms on LayerManagerOGL should ensure their widget is able to
        * deal with it though!
        */
       if (layerManager->Initialize()) {
--- a/widget/src/xpwidgets/nsBaseWidget.h
+++ b/widget/src/xpwidgets/nsBaseWidget.h
@@ -110,19 +110,20 @@ public:
   virtual nsTransparencyMode GetTransparencyMode();
   virtual void            GetWindowClipRegion(nsTArray<nsIntRect>* aRects);
   NS_IMETHOD              SetWindowShadowStyle(PRInt32 aStyle);
   virtual void            SetShowsToolbarButton(PRBool aShow) {}
   NS_IMETHOD              HideWindowChrome(PRBool aShouldHide);
   NS_IMETHOD              MakeFullScreen(PRBool aFullScreen);
   virtual nsDeviceContext* GetDeviceContext();
   virtual nsIToolkit*     GetToolkit();
-  virtual LayerManager*   GetLayerManager(LayerManagerPersistence aPersistence,
+  virtual LayerManager*   GetLayerManager(PLayersChild* aShadowManager = nsnull,
+                                          LayersBackend aBackendHint = LayerManager::LAYERS_NONE,
+                                          LayerManagerPersistence aPersistence = LAYER_MANAGER_CURRENT,
                                           bool* aAllowRetaining = nsnull);
-  using nsIWidget::GetLayerManager;
 
   virtual void            DrawOver(LayerManager* aManager, nsIntRect aRect) {}
   virtual void            UpdateThemeGeometries(const nsTArray<ThemeGeometry>& aThemeGeometries) {}
   virtual gfxASurface*    GetThebesSurface();
   NS_IMETHOD              SetModal(PRBool aModal); 
   NS_IMETHOD              SetWindowClass(const nsAString& xulWinType);
   NS_IMETHOD              SetBounds(const nsIntRect &aRect);
   NS_IMETHOD              GetBounds(nsIntRect &aRect);