Bug 648484, part 3 and part 3.1: 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>
Wed, 13 Jul 2011 22:43:43 -0700
changeset 73852 6b041c05b2cbc725e3192223a60bf6ab4b06c6bf
parent 73851 b8e675ff425d9612aa9fb1ce5c4eb551a2100cc8
child 73853 00dd5138b32d7f5f0f87f966881cf2a62244ab7f
push id67
push userclegnitto@mozilla.com
push dateFri, 04 Nov 2011 22:39:41 +0000
treeherdermozilla-release@04778346a3b0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc
bugs648484
milestone8.0a1
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 648484, part 3 and part 3.1: 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/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
@@ -455,68 +455,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
@@ -532,16 +540,19 @@ TabChild::RecvShow(const nsIntSize& size
 
     return InitTabChildGlobal();
 }
 
 bool
 TabChild::RecvMove(const nsIntSize& size)
 {
     printf("[TabChild] RESIZE to (w,h)= (%ud, %ud)\n", size.width, size.height);
+    if (!mRemoteFrame) {
+        return true;
+    }
 
     mWidget->Resize(0, 0, size.width, size.height,
                     PR_TRUE);
 
     nsCOMPtr<nsIBaseWindow> baseWin = do_QueryInterface(mWebNav);
     baseWin->SetPositionAndSize(0, 0, size.width, size.height,
                                 PR_TRUE);
     return true;
@@ -770,17 +781,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)
@@ -820,20 +833,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*
@@ -941,32 +956,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
@@ -739,18 +739,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
@@ -510,31 +510,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,20 +560,21 @@ 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->GetOwnerContent(),
-                      FrameMetrics::ROOT_SCROLL_ID);
+  if (aFrameLoader) {
+    mContentViews[FrameMetrics::ROOT_SCROLL_ID] =
+      new nsContentView(aFrameLoader->GetOwnerContent(),
+                        FrameMetrics::ROOT_SCROLL_ID);
+  }
 }
 
 RenderFrameParent::~RenderFrameParent()
 {}
 
 void
 RenderFrameParent::Destroy()
 {
@@ -696,49 +697,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
@@ -94,17 +94,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/windows/nsWindow.cpp
+++ b/widget/src/windows/nsWindow.cpp
@@ -3168,18 +3168,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,17 +110,19 @@ 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,
+                                          LayersBackend aBackendHint,
+                                          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);