Bug 745148, part 9: Hook up the pieces and enable direct compositor. r=roc
authorChris Jones <jones.chris.g@gmail.com>
Tue, 17 Jul 2012 16:59:45 -0700
changeset 105604 4a58089672882ca7f22e9866d2becf90afced9d5
parent 105603 aeafc64692a5f965917ba07b1f7bf2d99413047e
child 105605 fcba8ae674df875450cf3c94a527e775949d970f
push id214
push userakeybl@mozilla.com
push dateWed, 14 Nov 2012 20:38:59 +0000
treeherdermozilla-release@c8b08ec8e1aa [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc
bugs745148
milestone17.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 745148, part 9: Hook up the pieces and enable direct compositor. r=roc
b2g/app/b2g.js
dom/ipc/PBrowser.ipdl
dom/ipc/TabChild.cpp
dom/ipc/TabChild.h
dom/ipc/TabParent.cpp
dom/ipc/TabParent.h
gfx/layers/ipc/CompositorChild.cpp
gfx/layers/ipc/CompositorChild.h
gfx/layers/ipc/CompositorParent.cpp
gfx/layers/ipc/CompositorParent.h
gfx/layers/ipc/PCompositor.ipdl
gfx/thebes/gfxPlatform.cpp
layout/ipc/PRenderFrame.ipdl
layout/ipc/RenderFrameChild.cpp
layout/ipc/RenderFrameChild.h
layout/ipc/RenderFrameParent.cpp
layout/ipc/RenderFrameParent.h
widget/nsIWidget.h
widget/xpwidgets/PuppetWidget.cpp
widget/xpwidgets/PuppetWidget.h
widget/xpwidgets/nsBaseWidget.cpp
--- a/b2g/app/b2g.js
+++ b/b2g/app/b2g.js
@@ -240,17 +240,17 @@ pref("editor.singleLine.pasteNewlines", 
 
 // threshold where a tap becomes a drag, in 1/240" reference pixels
 // The names of the preferences are to be in sync with nsEventStateManager.cpp
 pref("ui.dragThresholdX", 25);
 pref("ui.dragThresholdY", 25);
 
 // Layers Acceleration
 pref("layers.acceleration.disabled", false);
-pref("layers.offmainthreadcomposition.enabled", false);
+pref("layers.offmainthreadcomposition.enabled", true);
 pref("layers.async-video.enabled", true);
 
 // Web Notifications
 pref("notification.feature.enabled", true);
 
 // IndexedDB
 pref("indexedDB.feature.enabled", true);
 pref("dom.indexedDB.warningQuota", 5);
--- a/dom/ipc/PBrowser.ipdl
+++ b/dom/ipc/PBrowser.ipdl
@@ -15,16 +15,17 @@ include protocol PIndexedDB;
 
 include "mozilla/dom/TabMessageUtils.h";
 include "gfxMatrix.h";
 include "mozilla/net/NeckoMessageUtils.h";
 include "IPC/nsGUIEventIPC.h";
 
 using IPC::URI;
 using gfxMatrix;
+using mozilla::LayersBackend;
 using mozilla::WindowsHandle;
 using nscolor;
 using nsCompositionEvent;
 using nsIMEUpdatePreference;
 using nsIntSize;
 using nsKeyEvent;
 using nsMouseEvent;
 using nsMouseScrollEvent;
@@ -169,17 +170,18 @@ parent:
 
     PContentDialog(PRUint32 aType, nsCString aName, nsCString aFeatures,
                    PRInt32[] aIntParams, nsString[] aStringParams);
 
     /**
      * Create a layout frame (encapsulating a remote layer tree) for
      * the page that is currently loaded in the <browser>.
      */
-    async PRenderFrame();
+    sync PRenderFrame()
+        returns (LayersBackend backend, int32_t maxTextureSize, uint64_t layersId);
 
     /** 
      * Starts an offline application cache update.
      * @param manifestURI
      *   URI of the manifest to fetch, the application cache group ID
      * @param documentURI
      *   URI of the document that referred the manifest
      * @param clientID
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -1,67 +1,69 @@
 /* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 8; -*- */
 /* vim: set sw=2 sts=2 ts=8 et tw=80 : */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include "TabChild.h"
-#include "mozilla/IntentionalCrash.h"
-#include "mozilla/dom/PContentChild.h"
-#include "mozilla/dom/PContentDialogChild.h"
-#include "mozilla/layers/PLayersChild.h"
-#include "mozilla/layout/RenderFrameChild.h"
-#include "mozilla/docshell/OfflineCacheUpdateChild.h"
+#include "base/basictypes.h"
 
 #include "BasicLayers.h"
-#include "nsIWebBrowser.h"
-#include "nsIWebBrowserSetup.h"
-#include "nsEmbedCID.h"
+#include "IndexedDBChild.h"
+#include "mozilla/IntentionalCrash.h"
+#include "mozilla/docshell/OfflineCacheUpdateChild.h"
+#include "mozilla/dom/PContentChild.h"
+#include "mozilla/dom/PContentDialogChild.h"
+#include "mozilla/ipc/DocumentRendererChild.h"
+#include "mozilla/layers/CompositorChild.h"
+#include "mozilla/layers/PLayersChild.h"
+#include "mozilla/layout/RenderFrameChild.h"
 #include "nsComponentManagerUtils.h"
+#include "nsComponentManagerUtils.h"
+#include "nsContentUtils.h"
+#include "nsEmbedCID.h"
+#include "nsEventListenerManager.h"
 #include "nsIBaseWindow.h"
+#include "nsIComponentManager.h"
+#include "nsIDOMClassInfo.h"
+#include "nsIDOMEvent.h"
 #include "nsIDOMWindow.h"
-#include "nsIWebProgress.h"
+#include "nsIDOMWindowUtils.h"
 #include "nsIDocShell.h"
 #include "nsIDocShellTreeItem.h"
-#include "nsThreadUtils.h"
+#include "nsIFrame.h"
+#include "nsIInterfaceRequestorUtils.h"
 #include "nsIInterfaceRequestorUtils.h"
-#include "mozilla/ipc/DocumentRendererChild.h"
-#include "nsIInterfaceRequestorUtils.h"
-#include "nsPIDOMWindow.h"
-#include "nsIDOMWindowUtils.h"
+#include "nsIJSContextStack.h"
+#include "nsIJSRuntimeService.h"
+#include "nsISSLStatusProvider.h"
+#include "nsIScriptContext.h"
+#include "nsIScriptGlobalObject.h"
+#include "nsIScriptSecurityManager.h"
+#include "nsISecureBrowserUI.h"
+#include "nsIServiceManager.h"
 #include "nsISupportsImpl.h"
 #include "nsIURI.h"
+#include "nsIView.h"
+#include "nsIWebBrowser.h"
 #include "nsIWebBrowserFocus.h"
-#include "nsIDOMEvent.h"
-#include "nsIComponentManager.h"
-#include "nsIServiceManager.h"
-#include "nsIJSRuntimeService.h"
-#include "nsContentUtils.h"
-#include "nsIDOMClassInfo.h"
+#include "nsIWebBrowserSetup.h"
+#include "nsIWebProgress.h"
 #include "nsIXPCSecurityManager.h"
-#include "nsIJSContextStack.h"
-#include "nsComponentManagerUtils.h"
-#include "nsIScriptSecurityManager.h"
-#include "nsScriptLoader.h"
+#include "nsInterfaceHashtable.h"
+#include "nsPIDOMWindow.h"
 #include "nsPIWindowRoot.h"
-#include "nsIScriptContext.h"
-#include "nsInterfaceHashtable.h"
 #include "nsPresContext.h"
-#include "nsIScriptGlobalObject.h"
+#include "nsScriptLoader.h"
+#include "nsSerializationHelper.h"
+#include "nsThreadUtils.h"
 #include "nsWeakReference.h"
-#include "nsISecureBrowserUI.h"
-#include "nsISSLStatusProvider.h"
-#include "nsSerializationHelper.h"
-#include "nsIFrame.h"
-#include "nsIView.h"
-#include "nsEventListenerManager.h"
 #include "PCOMContentPermissionRequestChild.h"
+#include "TabChild.h"
 #include "xpcpublic.h"
-#include "IndexedDBChild.h"
 
 using namespace mozilla::dom;
 using namespace mozilla::ipc;
 using namespace mozilla::layers;
 using namespace mozilla::layout;
 using namespace mozilla::docshell;
 using namespace mozilla::dom::indexedDB;
 
@@ -491,16 +493,22 @@ TabChild::DestroyWindow()
     }
 
     if (mRemoteFrame) {
         mRemoteFrame->Destroy();
         mRemoteFrame = nsnull;
     }
 }
 
+bool
+TabChild::UseDirectCompositor()
+{
+    return !!CompositorChild::Get();
+}
+
 void
 TabChild::ActorDestroy(ActorDestroyReason why)
 {
   if (mTabChildGlobal) {
     // The messageManager relays messages via the TabChild which
     // no longer exists.
     static_cast<nsFrameMessageManager*>
       (mTabChildGlobal->mMessageManager.get())->Disconnect();
@@ -949,17 +957,19 @@ TabChild::RecvDestroy()
 
   // XXX what other code in ~TabChild() should we be running here?
   DestroyWindow();
 
   return Send__delete__(this);
 }
 
 PRenderFrameChild*
-TabChild::AllocPRenderFrame()
+TabChild::AllocPRenderFrame(LayersBackend* aBackend,
+                            int32_t* aMaxTextureSize,
+                            uint64_t* aLayersId)
 {
     return new RenderFrameChild();
 }
 
 bool
 TabChild::DeallocPRenderFrame(PRenderFrameChild* aFrame)
 {
     delete aFrame;
@@ -1015,29 +1025,40 @@ TabChild::InitWidget(const nsIntSize& si
     }
     mWidget->Create(
         nsnull, 0,              // no parents
         nsIntRect(nsIntPoint(0, 0), size),
         nsnull,                 // HandleWidgetEvent
         nsnull                  // nsDeviceContext
         );
 
+    LayerManager::LayersBackend be;
+    uint64_t id;
+    int32_t maxTextureSize;
     RenderFrameChild* remoteFrame =
-        static_cast<RenderFrameChild*>(SendPRenderFrameConstructor());
+        static_cast<RenderFrameChild*>(SendPRenderFrameConstructor(
+                                           &be, &maxTextureSize, &id));
     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");
-    LayerManager::LayersBackend be;
-    PRInt32 maxTextureSize;
-    uint64_t id;
-    PLayersChild* shadowManager = remoteFrame->SendPLayersConstructor(&be, &maxTextureSize, &id);
+    PLayersChild* shadowManager = nsnull;
+    if (id != 0) {
+        // Pushing layers transactions directly to a separate
+        // compositor context.
+        shadowManager =
+            CompositorChild::Get()->SendPLayersConstructor(be, id,
+                                                           &be,
+                                                           &maxTextureSize);
+    } else {
+        // Pushing transactions to the parent content.
+        shadowManager = remoteFrame->SendPLayersConstructor();
+    }
+
     if (!shadowManager) {
       NS_WARNING("failed to construct LayersChild");
       // This results in |remoteFrame| being deleted.
       PRenderFrameChild::Send__delete__(remoteFrame);
       return false;
     }
 
     ShadowLayerForwarder* lf =
@@ -1055,16 +1076,33 @@ void
 TabChild::SetBackgroundColor(const nscolor& aColor)
 {
   if (mLastBackgroundColor != aColor) {
     mLastBackgroundColor = aColor;
     SendSetBackgroundColor(mLastBackgroundColor);
   }
 }
 
+void
+TabChild::NotifyPainted()
+{
+    if (UseDirectCompositor()) {
+        // FIXME/bug XXXXXX: in theory, we should only have to push a
+        // txn to our remote frame once, and the
+        // display-list/FrameLayerBuilder code there will manage the
+        // tree from there on.  But in practice, that doesn't work for
+        // some unknown reason.  So for now, always notify the content
+        // thread in the parent process.  It's wasteful but won't
+        // result in unnecessary repainting or even composites
+        // (usually, unless timing is unlucky), since they're
+        // throttled.
+        mRemoteFrame->SendNotifyCompositorTransaction();
+    }
+}
+
 NS_IMETHODIMP
 TabChild::GetMessageManager(nsIContentFrameMessageManager** aResult)
 {
   if (mTabChildGlobal) {
     NS_ADDREF(*aResult = mTabChildGlobal);
     return NS_OK;
   }
   *aResult = nsnull;
--- a/dom/ipc/TabChild.h
+++ b/dom/ipc/TabChild.h
@@ -227,32 +227,38 @@ public:
 
     nsIWebNavigation* WebNavigation() { return mWebNav; }
 
     JSContext* GetJSContext() { return mCx; }
 
     nsIPrincipal* GetPrincipal() { return mPrincipal; }
 
     void SetBackgroundColor(const nscolor& aColor);
+
+    void NotifyPainted();
 protected:
     NS_OVERRIDE
-    virtual PRenderFrameChild* AllocPRenderFrame();
+    virtual PRenderFrameChild* AllocPRenderFrame(LayersBackend* aBackend,
+                                                 int32_t* aMaxTextureSize,
+                                                 uint64_t* aLayersId);
     NS_OVERRIDE
     virtual bool DeallocPRenderFrame(PRenderFrameChild* aFrame);
     NS_OVERRIDE
     virtual bool RecvDestroy();
 
     nsEventStatus DispatchWidgetEvent(nsGUIEvent& event);
 
     virtual PIndexedDBChild* AllocPIndexedDB(const nsCString& aASCIIOrigin,
                                              bool* /* aAllowed */);
 
     virtual bool DeallocPIndexedDB(PIndexedDBChild* aActor);
 
 private:
+    bool UseDirectCompositor();
+
     void ActorDestroy(ActorDestroyReason why);
 
     bool InitTabChildGlobal();
     bool InitWidget(const nsIntSize& size);
     void DestroyWindow();
 
     // Call RecvShow(nsIntSize(0, 0)) and block future calls to RecvShow().
     void DoFakeShow();
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -841,20 +841,23 @@ TabParent::HandleDelayedDialogs()
   if (ShouldDelayDialogs() && mDelayedDialogs.Length()) {
     nsContentUtils::DispatchTrustedEvent(frame->OwnerDoc(), frame,
                                          NS_LITERAL_STRING("MozDelayedModalDialog"),
                                          true, true);
   }
 }
 
 PRenderFrameParent*
-TabParent::AllocPRenderFrame()
+TabParent::AllocPRenderFrame(LayersBackend* aBackend,
+                             int32_t* aMaxTextureSize,
+                             uint64_t* aLayersId)
 {
   nsRefPtr<nsFrameLoader> frameLoader = GetFrameLoader();
-  return new RenderFrameParent(frameLoader);
+  return new RenderFrameParent(frameLoader,
+                               aBackend, aMaxTextureSize, aLayersId);
 }
 
 bool
 TabParent::DeallocPRenderFrame(PRenderFrameParent* aFrame)
 {
   delete aFrame;
   return true;
 }
--- a/dom/ipc/TabParent.h
+++ b/dom/ipc/TabParent.h
@@ -198,17 +198,19 @@ protected:
       nsCOMPtr<nsIDialogParamBlock> mParams;
     };
     InfallibleTArray<DelayedDialogData*> mDelayedDialogs;
 
     bool ShouldDelayDialogs();
     bool AllowContentIME();
 
     NS_OVERRIDE
-    virtual PRenderFrameParent* AllocPRenderFrame();
+    virtual PRenderFrameParent* AllocPRenderFrame(LayersBackend* aBackend,
+                                                  int32_t* aMaxTextureSize,
+                                                  uint64_t* aLayersId);
     NS_OVERRIDE
     virtual bool DeallocPRenderFrame(PRenderFrameParent* aFrame);
 
     // IME
     static TabParent *mIMETabParent;
     nsString mIMECacheText;
     PRUint32 mIMESelectionAnchor;
     PRUint32 mIMESelectionFocus;
--- a/gfx/layers/ipc/CompositorChild.cpp
+++ b/gfx/layers/ipc/CompositorChild.cpp
@@ -65,17 +65,20 @@ CompositorChild::Create(Transport* aTran
 CompositorChild::Get()
 {
   // This is only expected to be used in child processes.
   MOZ_ASSERT(XRE_GetProcessType() != GeckoProcessType_Default);
   return sCompositor;
 }
 
 PLayersChild*
-CompositorChild::AllocPLayers(const LayersBackend &aBackend, const uint64_t& aId, int* aMaxTextureSize)
+CompositorChild::AllocPLayers(const LayersBackend& aBackendHint,
+                              const uint64_t& aId,
+                              LayersBackend* aBackend,
+                              int* aMaxTextureSize)
 {
   return new ShadowLayersChild();
 }
 
 bool
 CompositorChild::DeallocPLayers(PLayersChild* actor)
 {
   delete actor;
--- a/gfx/layers/ipc/CompositorChild.h
+++ b/gfx/layers/ipc/CompositorChild.h
@@ -31,17 +31,20 @@ public:
    * the compositor's context.
    */
   static PCompositorChild*
   Create(Transport* aTransport, ProcessId aOtherProcess);
 
   static PCompositorChild* Get();
 
 protected:
-  virtual PLayersChild* AllocPLayers(const LayersBackend &aBackend, const uint64_t& aId, int* aMaxTextureSize);
+  virtual PLayersChild* AllocPLayers(const LayersBackend& aBackendHint,
+                                     const uint64_t& aId,
+                                     LayersBackend* aBackend,
+                                     int* aMaxTextureSize);
   virtual bool DeallocPLayers(PLayersChild *aChild);
 
   virtual void ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
 
 private:
   nsRefPtr<LayerManager> mLayerManager;
 
   // When we're in a child process, this is the process-global
--- a/gfx/layers/ipc/CompositorParent.cpp
+++ b/gfx/layers/ipc/CompositorParent.cpp
@@ -619,30 +619,33 @@ CompositorParent::ShadowLayersUpdated(Sh
   mLayerManager->SetRoot(root);
   if (root) {
     SetShadowProperties(root);
   }
   ScheduleComposition();
 }
 
 PLayersParent*
-CompositorParent::AllocPLayers(const LayersBackend& aBackendType,
+CompositorParent::AllocPLayers(const LayersBackend& aBackendHint,
                                const uint64_t& aId,
+                               LayersBackend* aBackend,
                                int32_t* aMaxTextureSize)
 {
   MOZ_ASSERT(aId == 0);
 
   // mWidget doesn't belong to the compositor thread, so it should be set to
   // NULL before returning from this method, to avoid accessing it elsewhere.
   nsIntRect rect;
   mWidget->GetBounds(rect);
   mWidgetSize.width = rect.width;
   mWidgetSize.height = rect.height;
 
-  if (aBackendType == LayerManager::LAYERS_OPENGL) {
+  *aBackend = aBackendHint;
+
+  if (aBackendHint == LayerManager::LAYERS_OPENGL) {
     nsRefPtr<LayerManagerOGL> layerManager;
     layerManager =
       new LayerManagerOGL(mWidget, mEGLSurfaceSize.width, mEGLSurfaceSize.height, mRenderToEGLSurface);
     mWidget = NULL;
     mLayerManager = layerManager;
     ShadowLayerManager* shadowManager = layerManager->AsShadowManager();
     if (shadowManager) {
       shadowManager->SetCompositorID(mCompositorID);  
@@ -654,17 +657,17 @@ CompositorParent::AllocPLayers(const Lay
     }
 
     ShadowLayerManager* slm = layerManager->AsShadowManager();
     if (!slm) {
       return NULL;
     }
     *aMaxTextureSize = layerManager->GetMaxTextureSize();
     return new ShadowLayersParent(slm, this, 0);
-  } else if (aBackendType == LayerManager::LAYERS_BASIC) {
+  } else if (aBackendHint == LayerManager::LAYERS_BASIC) {
     nsRefPtr<LayerManager> layerManager = new BasicShadowLayerManager(mWidget);
     mWidget = NULL;
     mLayerManager = layerManager;
     ShadowLayerManager* slm = layerManager->AsShadowManager();
     if (!slm) {
       return NULL;
     }
     *aMaxTextureSize = layerManager->GetMaxTextureSize();
@@ -763,16 +766,17 @@ public:
   // FIXME/bug 774388: work out what shutdown protocol we need.
   virtual bool RecvWillStop() MOZ_OVERRIDE { return true; }
   virtual bool RecvStop() MOZ_OVERRIDE { return true; }
   virtual bool RecvPause() MOZ_OVERRIDE { return true; }
   virtual bool RecvResume() MOZ_OVERRIDE { return true; }
 
   virtual PLayersParent* AllocPLayers(const LayersBackend& aBackendType,
                                       const uint64_t& aId,
+                                      LayersBackend* aBackend,
                                       int32_t* aMaxTextureSize) MOZ_OVERRIDE;
   virtual bool DeallocPLayers(PLayersParent* aLayers) MOZ_OVERRIDE;
 
   virtual void ShadowLayersUpdated(ShadowLayersParent* aLayerTree,
                                    bool isFirstPaint) MOZ_OVERRIDE;
 
 private:
   void DeferredDestroy();
@@ -841,26 +845,26 @@ CrossProcessCompositorParent::ActorDestr
   MessageLoop::current()->PostTask(
     FROM_HERE,
     NewRunnableMethod(this, &CrossProcessCompositorParent::DeferredDestroy));
 }
 
 PLayersParent*
 CrossProcessCompositorParent::AllocPLayers(const LayersBackend& aBackendType,
                                            const uint64_t& aId,
+                                           LayersBackend* aBackend,
                                            int32_t* aMaxTextureSize)
 {
   MOZ_ASSERT(aId != 0);
 
   nsRefPtr<LayerManager> lm = sCurrentCompositor->GetLayerManager();
+  *aBackend = lm->GetBackendType();
   *aMaxTextureSize = lm->GetMaxTextureSize();
   return new ShadowLayersParent(lm->AsShadowManager(), this, aId);
-
-   return nsnull;
- }
+}
  
 bool
 CrossProcessCompositorParent::DeallocPLayers(PLayersParent* aLayers)
 {
   ShadowLayersParent* slp = static_cast<ShadowLayersParent*>(aLayers);
   RemoveIndirectTree(slp->GetId());
   delete aLayers;
   return true;
--- a/gfx/layers/ipc/CompositorParent.h
+++ b/gfx/layers/ipc/CompositorParent.h
@@ -112,17 +112,20 @@ public:
   /**
    * A new child process has been configured to push transactions
    * directly to us.  Transport is to its thread context.
    */
   static PCompositorParent*
   Create(Transport* aTransport, ProcessId aOtherProcess);
 
 protected:
-  virtual PLayersParent* AllocPLayers(const LayersBackend& aBackendType, const uint64_t& aId, int32_t* aMaxTextureSize);
+  virtual PLayersParent* AllocPLayers(const LayersBackend& aBackendHint,
+                                      const uint64_t& aId,
+                                      LayersBackend* aBackend,
+                                      int32_t* aMaxTextureSize);
   virtual bool DeallocPLayers(PLayersParent* aLayers);
   virtual void ScheduleTask(CancelableTask*, int);
   virtual void Composite();
   virtual void SetFirstPaintViewport(const nsIntPoint& aOffset, float aZoom, const nsIntRect& aPageRect, const gfx::Rect& aCssPageRect);
   virtual void SetPageRect(const gfx::Rect& aCssPageRect);
   virtual void SyncViewportInfo(const nsIntRect& aDisplayPort, float aDisplayResolution, bool aLayersUpdated,
                                 nsIntPoint& aScrollOffset, float& aScaleX, float& aScaleY);
   void SetEGLSurfaceSize(int width, int height);
--- a/gfx/layers/ipc/PCompositor.ipdl
+++ b/gfx/layers/ipc/PCompositor.ipdl
@@ -33,14 +33,14 @@ parent:
   // Clean up in preparation for own destruction.
   sync Stop();
 
   // Pause/resume the compositor. These are intended to be used on mobile, when
   // the compositor needs to pause/resume in lockstep with the application.
   sync Pause();
   sync Resume();
 
-  sync PLayers(LayersBackend backend, uint64_t id)
-    returns (int32_t maxTextureSize);
+  sync PLayers(LayersBackend backendHint, uint64_t id)
+    returns (LayersBackend backend, int32_t maxTextureSize);
 };
 
 } // layers
 } // mozilla
--- a/gfx/thebes/gfxPlatform.cpp
+++ b/gfx/thebes/gfxPlatform.cpp
@@ -255,25 +255,16 @@ gfxPlatform::Init()
 #ifdef MOZ_X11
     // On X11 platforms only use OMTC if firefox was initalized with thread-safe 
     // X11 (else it would crash).
     useOffMainThreadCompositing = (PR_GetEnv("MOZ_USE_OMTC") != NULL);
 #else
     useOffMainThreadCompositing = Preferences::GetBool(
           "layers.offmainthreadcomposition.enabled", 
           false);
-    // Until https://bugzilla.mozilla.org/show_bug.cgi?id=745148 lands,
-    // we use either omtc or content processes, but not both.  Prefer
-    // OOP content to omtc.  (Currently, this only affects b2g.)
-    //
-    // See https://bugzilla.mozilla.org/show_bug.cgi?id=761962 .
-    if (!Preferences::GetBool("dom.ipc.tabs.disabled", true)) {
-        // Disable omtc if OOP content isn't force-disabled.
-        useOffMainThreadCompositing = false;
-    }
 #endif
 
     if (useOffMainThreadCompositing && (XRE_GetProcessType() == 
                                         GeckoProcessType_Default)) {
         CompositorParent::StartUp();
         if (Preferences::GetBool("layers.async-video.enabled",false)) {
             ImageBridgeChild::StartUp();
         }
--- a/layout/ipc/PRenderFrame.ipdl
+++ b/layout/ipc/PRenderFrame.ipdl
@@ -34,21 +34,26 @@ parent:
      *  - direct shadow tree: updates are sent to parent
      *  - indirect: the parent holds a reference (ID) to a shadow tree
      *    that's managed by the compositor.  During composition, the
      *    shadow tree is looked up and grafted appropriately
      *
      * |id| is set to 0 in the "direct" case, and to a whole number
      * in the "indirect" case.
      */
-     sync PLayers()
-       returns (LayersBackend backend, int32_t maxTextureSize, uint64_t layersId);
+    async PLayers();
+
+    async NotifyCompositorTransaction();
 
     async __delete__();
 
-state EMPTY:
+state EMPTY_OR_DIRECT_COMPOSITOR:
     recv PLayers goto HAVE_CONTENT;
+    recv NotifyCompositorTransaction goto EMPTY_OR_DIRECT_COMPOSITOR;
+    recv __delete__;
+
 state HAVE_CONTENT:
+    recv NotifyCompositorTransaction goto HAVE_CONTENT;
     recv __delete__;
 };
 
 } // namespace layout
 } // namespace mozilla
--- a/layout/ipc/RenderFrameChild.cpp
+++ b/layout/ipc/RenderFrameChild.cpp
@@ -28,18 +28,17 @@ RenderFrameChild::Destroy()
     // |layers| was just deleted, take care
   }
 
   Send__delete__(this);
   // WARNING: |this| is dead, hands off
 }
 
 PLayersChild*
-RenderFrameChild::AllocPLayers(LayerManager::LayersBackend* aBackendType,
-                               int* aMaxTextureSize, uint64_t* aId)
+RenderFrameChild::AllocPLayers()
 {
   return new ShadowLayersChild();
 }
 
 bool
 RenderFrameChild::DeallocPLayers(PLayersChild* aLayers)
 {
   delete aLayers;
--- a/layout/ipc/RenderFrameChild.h
+++ b/layout/ipc/RenderFrameChild.h
@@ -18,18 +18,17 @@ class RenderFrameChild : public PRenderF
 public:
   RenderFrameChild() {}
   virtual ~RenderFrameChild() {}
 
   void Destroy();
 
 protected:
   NS_OVERRIDE
-  virtual PLayersChild* AllocPLayers(LayerManager::LayersBackend* aBackendType,
-                                     int* aMaxTextureSize, uint64_t* aId);
+  virtual PLayersChild* AllocPLayers();
   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
@@ -1,31 +1,32 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  * vim: sw=2 ts=8 et :
  */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include "mozilla/layers/ShadowLayersParent.h"
+#include "base/basictypes.h"
 
 #include "BasicLayers.h"
+#include "gfx3DMatrix.h"
 #include "LayerManagerOGL.h"
 #ifdef MOZ_ENABLE_D3D9_LAYER
-#include "LayerManagerD3D9.h"
+# include "LayerManagerD3D9.h"
 #endif //MOZ_ENABLE_D3D9_LAYER
+#include "mozilla/layers/CompositorParent.h"
+#include "mozilla/layers/ShadowLayersParent.h"
+#include "nsContentUtils.h"
+#include "nsFrameLoader.h"
+#include "nsIObserver.h"
+#include "nsSubDocumentFrame.h"
+#include "nsViewportFrame.h"
 #include "RenderFrameParent.h"
 
-#include "gfx3DMatrix.h"
-#include "nsFrameLoader.h"
-#include "nsViewportFrame.h"
-#include "nsSubDocumentFrame.h"
-#include "nsIObserver.h"
-#include "nsContentUtils.h"
-
 typedef nsContentView::ViewConfig ViewConfig;
 using namespace mozilla::layers;
 
 namespace mozilla {
 namespace layout {
 
 typedef FrameMetrics::ViewID ViewID;
 typedef RenderFrameParent::ViewMap ViewMap;
@@ -439,24 +440,47 @@ BuildBackgroundPatternFor(ContainerLayer
   nsIntRegion bgRgn(frameRect);
   bgRgn.Sub(bgRgn, localIntContentVis);
   bgRgn.MoveBy(-frameRect.TopLeft());
   layer->SetVisibleRegion(bgRgn);
 
   aContainer->InsertAfter(layer, nsnull);
 }
 
-RenderFrameParent::RenderFrameParent(nsFrameLoader* aFrameLoader)
-  : mFrameLoader(aFrameLoader)
+already_AddRefed<LayerManager>
+GetFrom(nsFrameLoader* aFrameLoader)
+{
+  nsIDocument* doc = aFrameLoader->GetOwnerDoc();
+  return nsContentUtils::LayerManagerForDocument(doc);
+}
+
+RenderFrameParent::RenderFrameParent(nsFrameLoader* aFrameLoader,
+                                     LayerManager::LayersBackend* aBackendType,
+                                     int* aMaxTextureSize,
+                                     uint64_t* aId)
+  : mLayersId(0)
+  , mFrameLoader(aFrameLoader)
   , mFrameLoaderDestroyed(false)
   , mBackgroundColor(gfxRGBA(1, 1, 1))
 {
-  if (aFrameLoader) {
-    mContentViews[FrameMetrics::ROOT_SCROLL_ID] =
-      new nsContentView(aFrameLoader, FrameMetrics::ROOT_SCROLL_ID);
+  mContentViews[FrameMetrics::ROOT_SCROLL_ID] =
+    new nsContentView(aFrameLoader, FrameMetrics::ROOT_SCROLL_ID);
+
+  *aBackendType = LayerManager::LAYERS_NONE;
+  *aMaxTextureSize = 0;
+  *aId = 0;
+
+  nsRefPtr<LayerManager> lm = GetFrom(mFrameLoader);
+  *aBackendType = lm->GetBackendType();
+  *aMaxTextureSize = lm->GetMaxTextureSize();
+
+  if (CompositorParent::CompositorLoop()) {
+    // Our remote frame will push layers updates to the compositor,
+    // and we'll keep an indirect reference to that tree.
+    *aId = mLayersId = CompositorParent::AllocateLayerTreeId();
   }
 }
 
 RenderFrameParent::~RenderFrameParent()
 {}
 
 void
 RenderFrameParent::Destroy()
@@ -487,44 +511,22 @@ RenderFrameParent::ContentViewScaleChang
   // shadow-space attributes updated. It's easiest to rebuild the view map.
   BuildViewMap();
 }
 
 void
 RenderFrameParent::ShadowLayersUpdated(ShadowLayersParent* aLayerTree,
                                        bool isFirstPaint)
 {
-  mFrameLoader->SetCurrentRemoteFrame(this);
-
   // View map must only contain views that are associated with the current
   // shadow layer tree. We must always update the map when shadow layers
   // are updated.
   BuildViewMap();
 
-  nsIFrame* docFrame = mFrameLoader->GetPrimaryFrameOfOwningContent();
-  if (!docFrame) {
-    // Bad, but nothing we can do about it (XXX/cjones: or is there?
-    // maybe bug 589337?).  When the new frame is created, we'll
-    // probably still be the current render frame and will get to draw
-    // our content then.  Or, we're shutting down and this update goes
-    // to /dev/null.
-    return;
-  }
-
-  // FIXME/cjones: we should collect the rects/regions updated for
-  // Painted*Layer() calls and pass that region to here, then only
-  // invalidate that rect
-  //
-  // We pass INVALIDATE_NO_THEBES_LAYERS here because we're
-  // invalidating the <browser> on behalf of its counterpart in the
-  // content process.  Not only do we not need to invalidate the
-  // shadow layers, things would just break if we did --- we have no
-  // way to repaint shadow layers from this process.
-  nsRect rect = nsRect(nsPoint(0, 0), docFrame->GetRect().Size());
-  docFrame->InvalidateWithFlags(rect, nsIFrame::INVALIDATE_NO_THEBES_LAYERS);
+  TriggerRepaint();
 }
 
 already_AddRefed<Layer>
 RenderFrameParent::BuildLayer(nsDisplayListBuilder* aBuilder,
                               nsIFrame* aFrame,
                               LayerManager* aManager,
                               const nsIntRect& aVisibleRect)
 {
@@ -540,16 +542,35 @@ RenderFrameParent::BuildLayer(nsDisplayL
     // widget's layer manager changed out from under us.  We need to
     // FIXME handle the former case somehow, probably with an API to
     // draw a manager's subtree.  The latter is bad bad bad, but the
     // the NS_ABORT_IF_FALSE() above will flag it.  Returning NULL
     // here will just cause the shadow subtree not to be rendered.
     return nsnull;
   }
 
+  uint64_t id = GetLayerTreeId();
+  if (0 != id) {
+    MOZ_ASSERT(!GetRootLayer());
+
+    nsRefPtr<RefLayer> layer = aManager->CreateRefLayer();
+    if (!layer) {
+      // Probably a temporary layer manager that doesn't know how to
+      // use ref layers.
+      return nsnull;
+    }
+    layer->SetReferentId(id);
+    layer->SetVisibleRegion(aVisibleRect);
+    nsIntPoint rootFrameOffset = GetRootFrameOffset(aFrame, aBuilder);
+    layer->SetTransform(
+      gfx3DMatrix::Translation(rootFrameOffset.x, rootFrameOffset.y, 0.0));
+
+    return layer.forget();
+  }
+
   if (mContainer) {
     ClearContainer(mContainer);
   }
 
   ContainerLayer* shadowRoot = GetRootLayer();
   if (!shadowRoot) {
     mContainer = nsnull;
     return nsnull;
@@ -603,45 +624,31 @@ RenderFrameParent::ActorDestroy(ActorDes
     // 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(LayerManager::LayersBackend* aBackendType,
-                                int* aMaxTextureSize,
-                                uint64_t* aId)
+bool
+RenderFrameParent::RecvNotifyCompositorTransaction()
 {
-  *aBackendType = LayerManager::LAYERS_NONE;
-  *aMaxTextureSize = 0;
-  *aId = 0;
+  TriggerRepaint();
+  return true;
+}
 
+PLayersParent*
+RenderFrameParent::AllocPLayers()
+{
   if (!mFrameLoader || mFrameLoaderDestroyed) {
     return nsnull;
   }
-
-  nsIDocument* doc = mFrameLoader->GetOwnerDoc();
-  nsRefPtr<LayerManager> lm = nsContentUtils::LayerManagerForDocument(doc);
-  ShadowLayerManager* slm = lm->AsShadowManager();
-  if (!slm) {
-     return nsnull;
-  }
-  *aBackendType = lm->GetBackendType();
-  *aMaxTextureSize = lm->GetMaxTextureSize();
-#if 0 // Enabled in later patch
-  if (CompositorParent::CompositorLoop()) {
-    // Our remote frame will push layers updates to the compositor,
-    // and we'll keep an indirect reference to that tree.
-    *aId = CompositorParent::AllocateLayerTreeId();
-  }
-#endif
-  return new ShadowLayersParent(slm, this, *aId);
+  nsRefPtr<LayerManager> lm = GetFrom(mFrameLoader);
+  return new ShadowLayersParent(lm->AsShadowManager(), this, 0);
 }
 
 bool
 RenderFrameParent::DeallocPLayers(PLayersParent* aLayers)
 {
   delete aLayers;
   return true;
 }
@@ -675,31 +682,58 @@ RenderFrameParent::BuildViewMap()
   if (newContentViews.empty()) {
     newContentViews[FrameMetrics::ROOT_SCROLL_ID] =
       FindViewForId(mContentViews, FrameMetrics::ROOT_SCROLL_ID);
   }
 
   mContentViews = newContentViews;
 }
 
+void
+RenderFrameParent::TriggerRepaint()
+{
+  mFrameLoader->SetCurrentRemoteFrame(this);
+
+  nsIFrame* docFrame = mFrameLoader->GetPrimaryFrameOfOwningContent();
+  if (!docFrame) {
+    // Bad, but nothing we can do about it (XXX/cjones: or is there?
+    // maybe bug 589337?).  When the new frame is created, we'll
+    // probably still be the current render frame and will get to draw
+    // our content then.  Or, we're shutting down and this update goes
+    // to /dev/null.
+    return;
+  }
+
+  // FIXME/cjones: we should collect the rects/regions updated for
+  // Painted*Layer() calls and pass that region to here, then only
+  // invalidate that rect
+  //
+  // We pass INVALIDATE_NO_THEBES_LAYERS here because we're
+  // invalidating the <browser> on behalf of its counterpart in the
+  // content process.  Not only do we not need to invalidate the
+  // shadow layers, things would just break if we did --- we have no
+  // way to repaint shadow layers from this process.
+  nsRect rect = nsRect(nsPoint(0, 0), docFrame->GetRect().Size());
+  docFrame->InvalidateWithFlags(rect, nsIFrame::INVALIDATE_NO_THEBES_LAYERS);
+}
+
 ShadowLayersParent*
 RenderFrameParent::GetShadowLayers() const
 {
   const nsTArray<PLayersParent*>& shadowParents = ManagedPLayersParent();
   NS_ABORT_IF_FALSE(shadowParents.Length() <= 1,
                     "can only support at most 1 ShadowLayersParent");
   return (shadowParents.Length() == 1) ?
     static_cast<ShadowLayersParent*>(shadowParents[0]) : nsnull;
 }
 
 uint64_t
 RenderFrameParent::GetLayerTreeId() const
 {
-  ShadowLayersParent* shadowLayers = GetShadowLayers();
-  return shadowLayers ? shadowLayers->GetId() : 0;
+  return mLayersId;
 }
 
 ContainerLayer*
 RenderFrameParent::GetRootLayer() const
 {
   ShadowLayersParent* shadowLayers = GetShadowLayers();
   return shadowLayers ? shadowLayers->GetRoot() : nsnull;
 }
--- a/layout/ipc/RenderFrameParent.h
+++ b/layout/ipc/RenderFrameParent.h
@@ -35,17 +35,20 @@ class RenderFrameParent : public PRender
   typedef mozilla::layers::Layer Layer;
   typedef mozilla::layers::LayerManager LayerManager;
   typedef mozilla::layers::ShadowLayersParent ShadowLayersParent;
   typedef FrameMetrics::ViewID ViewID;
 
 public:
   typedef std::map<ViewID, nsRefPtr<nsContentView> > ViewMap;
 
-  RenderFrameParent(nsFrameLoader* aFrameLoader);
+  RenderFrameParent(nsFrameLoader* aFrameLoader,
+                    LayerManager::LayersBackend* aBackendType,
+                    int* aMaxTextureSize,
+                    uint64_t* aId);
   virtual ~RenderFrameParent();
 
   void Destroy();
 
   /**
    * Helper function for getting a non-owning reference to a scrollable.
    * @param aId The ID of the frame.
    */
@@ -68,28 +71,34 @@ public:
 
   void OwnerContentChanged(nsIContent* aContent);
 
   void SetBackgroundColor(nscolor aColor) { mBackgroundColor = gfxRGBA(aColor); };
 
 protected:
   void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE;
 
-  virtual PLayersParent*
-  AllocPLayers(LayerManager::LayersBackend* aBackendType,
-               int* aMaxTextureSize, uint64_t* aLayersId) MOZ_OVERRIDE;
+  virtual bool RecvNotifyCompositorTransaction() MOZ_OVERRIDE;
+
+  virtual PLayersParent* AllocPLayers() MOZ_OVERRIDE;
   virtual bool DeallocPLayers(PLayersParent* aLayers) MOZ_OVERRIDE;
 
 private:
   void BuildViewMap();
+  void TriggerRepaint();
 
   ShadowLayersParent* GetShadowLayers() const;
   uint64_t GetLayerTreeId() const;
   ContainerLayer* GetRootLayer() const;
 
+  // When our child frame is pushing transactions directly to the
+  // compositor, this is the ID of its layer tree in the compositor's
+  // context.
+  uint64_t mLayersId;
+
   nsRefPtr<nsFrameLoader> mFrameLoader;
   nsRefPtr<ContainerLayer> mContainer;
 
   // This contains the views for all the scrollable frames currently in the
   // painted region of our remote content.
   ViewMap mContentViews;
 
   // True after Destroy() has been called, which is triggered
--- a/widget/nsIWidget.h
+++ b/widget/nsIWidget.h
@@ -33,17 +33,17 @@ class   nsIRollupListener;
 class   nsGUIEvent;
 class   imgIContainer;
 class   gfxASurface;
 class   nsIContent;
 class   ViewWrapper;
 
 namespace mozilla {
 namespace dom {
-class PBrowserChild;
+class TabChild;
 }
 namespace layers {
 class PLayersChild;
 }
 }
 
 /**
  * Callback function that processes events.
@@ -354,17 +354,17 @@ struct InputContextAction {
 } // namespace mozilla
 
 /**
  * The base class for all the widgets. It provides the interface for
  * all basic and necessary functionality.
  */
 class nsIWidget : public nsISupports {
   protected:
-    typedef mozilla::dom::PBrowserChild PBrowserChild;
+    typedef mozilla::dom::TabChild TabChild;
 
   public:
     typedef mozilla::layers::LayerManager LayerManager;
     typedef LayerManager::LayersBackend LayersBackend;
     typedef mozilla::layers::PLayersChild PLayersChild;
     typedef mozilla::widget::IMEState IMEState;
     typedef mozilla::widget::InputContext InputContext;
     typedef mozilla::widget::InputContextAction InputContextAction;
@@ -1538,17 +1538,17 @@ class nsIWidget : public nsISupports {
      * be fed to it.  Currently used in content processes.  NULL is
      * returned if puppet widgets aren't supported in this build
      * config, on this platform, or for this process type.
      *
      * This function is called "Create" to match CreateInstance().
      * The returned widget must still be nsIWidget::Create()d.
      */
     static already_AddRefed<nsIWidget>
-    CreatePuppetWidget(PBrowserChild *aTabChild);
+    CreatePuppetWidget(TabChild* aTabChild);
 
     /**
      * Reparent this widget's native widget.
      * @param aNewParent the native widget of aNewParent is the new native
      *                   parent widget
      */
     NS_IMETHOD ReparentNativeWidget(nsIWidget* aNewParent) = 0;
 
--- a/widget/xpwidgets/PuppetWidget.cpp
+++ b/widget/xpwidgets/PuppetWidget.cpp
@@ -1,23 +1,26 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  * vim: sw=2 ts=8 et :
  */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include "mozilla/dom/PBrowserChild.h"
+#include "base/basictypes.h"
+
 #include "BasicLayers.h"
+#include "gfxPlatform.h"
 #if defined(MOZ_ENABLE_D3D10_LAYER)
 # include "LayerManagerD3D10.h"
 #endif
-
-#include "gfxPlatform.h"
+#include "mozilla/dom/TabChild.h"
 #include "mozilla/Hal.h"
+#include "mozilla/layers/CompositorChild.h"
+#include "mozilla/layers/PLayersChild.h"
 #include "PuppetWidget.h"
 
 using namespace mozilla::dom;
 using namespace mozilla::hal;
 using namespace mozilla::layers;
 using namespace mozilla::widget;
 
 static void
@@ -25,17 +28,17 @@ InvalidateRegion(nsIWidget* aWidget, con
 {
   nsIntRegionRectIterator it(aRegion);
   while(const nsIntRect* r = it.Next()) {
     aWidget->Invalidate(*r);
   }
 }
 
 /*static*/ already_AddRefed<nsIWidget>
-nsIWidget::CreatePuppetWidget(PBrowserChild *aTabChild)
+nsIWidget::CreatePuppetWidget(TabChild* aTabChild)
 {
   NS_ABORT_IF_FALSE(nsIWidget::UsePuppetWidgets(),
                     "PuppetWidgets not allowed in this configuration");
 
   nsCOMPtr<nsIWidget> widget = new PuppetWidget(aTabChild);
   return widget.forget();
 }
 
@@ -58,17 +61,17 @@ MightNeedIMEFocus(const nsWidgetInitData
 
 
 // Arbitrary, fungible.
 const size_t PuppetWidget::kMaxDimension = 4000;
 
 NS_IMPL_ISUPPORTS_INHERITED1(PuppetWidget, nsBaseWidget,
                              nsISupportsWeakReference)
 
-PuppetWidget::PuppetWidget(PBrowserChild *aTabChild)
+PuppetWidget::PuppetWidget(TabChild* aTabChild)
   : mTabChild(aTabChild)
   , mDPI(-1)
 {
   MOZ_COUNT_CTOR(PuppetWidget);
 }
 
 PuppetWidget::~PuppetWidget()
 {
@@ -498,17 +501,18 @@ PuppetWidget::DispatchPaintEvent()
     if (LayerManager::LAYERS_D3D10 == mLayerManager->GetBackendType()) {
       DispatchEvent(&event, status);
     } else {
       nsRefPtr<gfxContext> ctx = new gfxContext(mSurface);
       ctx->Rectangle(gfxRect(0,0,0,0));
       ctx->Clip();
       AutoLayerManagerSetup setupLayerManager(this, ctx,
                                               BasicLayerManager::BUFFER_NONE);
-      DispatchEvent(&event, status);  
+      DispatchEvent(&event, status);
+      mTabChild->NotifyPainted();
     }
   }
 
   nsPaintEvent didPaintEvent(true, NS_DID_PAINT, this);
   DispatchEvent(&didPaintEvent, status);
 
   return NS_OK;
 }
--- a/widget/xpwidgets/PuppetWidget.h
+++ b/widget/xpwidgets/PuppetWidget.h
@@ -20,27 +20,33 @@
 #include "nsIScreenManager.h"
 #include "nsThreadUtils.h"
 #include "nsWeakReference.h"
 #include "mozilla/Attributes.h"
 
 class gfxASurface;
 
 namespace mozilla {
+
+namespace dom {
+class TabChild;
+}
+
 namespace widget {
 
 class PuppetWidget : public nsBaseWidget, public nsSupportsWeakReference
 {
+  typedef mozilla::dom::TabChild TabChild;
   typedef nsBaseWidget Base;
 
   // The width and height of the "widget" are clamped to this.
   static const size_t kMaxDimension;
 
 public:
-  PuppetWidget(PBrowserChild *aTabChild);
+  PuppetWidget(TabChild* aTabChild);
   virtual ~PuppetWidget();
 
   NS_DECL_ISUPPORTS_INHERITED
 
   NS_IMETHOD Create(nsIWidget*        aParent,
                     nsNativeWidget    aNativeParent,
                     const nsIntRect&  aRect,
                     EVENT_CALLBACK    aHandleEventFunction,
@@ -171,22 +177,22 @@ private:
     NS_DECL_NSIRUNNABLE
     PaintTask(PuppetWidget* widget) : mWidget(widget) {}
     void Revoke() { mWidget = nsnull; }
   private:
     PuppetWidget* mWidget;
   };
 
   // TabChild normally holds a strong reference to this PuppetWidget
-  // or its root ancestor, but each PuppetWidget also needs a reference
-  // back to TabChild (e.g. to delegate nsIWidget IME calls to chrome)
-  // So we hold a weak reference to TabChild (PBrowserChild) here.
-  // Since it's possible for TabChild to outlive the PuppetWidget,
-  // we clear this weak reference in Destroy()
-  PBrowserChild *mTabChild;
+  // or its root ancestor, but each PuppetWidget also needs a
+  // reference back to TabChild (e.g. to delegate nsIWidget IME calls
+  // to chrome) So we hold a weak reference to TabChild here.  Since
+  // it's possible for TabChild to outlive the PuppetWidget, we clear
+  // this weak reference in Destroy()
+  TabChild* mTabChild;
   // The "widget" to which we delegate events if we don't have an
   // event handler.
   nsRefPtr<PuppetWidget> mChild;
   nsIntRegion mDirtyRegion;
   nsRevocableEventPtr<PaintTask> mPaintTask;
   bool mEnabled;
   bool mVisible;
   // XXX/cjones: keeping this around until we teach LayerManager to do
--- a/widget/xpwidgets/nsBaseWidget.cpp
+++ b/widget/xpwidgets/nsBaseWidget.cpp
@@ -873,34 +873,31 @@ void nsBaseWidget::CreateCompositor()
   LayerManager* lm = CreateBasicLayerManager();
   MessageLoop *childMessageLoop = CompositorParent::CompositorLoop();
   mCompositorChild = new CompositorChild(lm);
   AsyncChannel *parentChannel = mCompositorParent->GetIPCChannel();
   AsyncChannel::Side childSide = mozilla::ipc::AsyncChannel::Child;
   mCompositorChild->Open(parentChannel, childMessageLoop, childSide);
   PRInt32 maxTextureSize;
   PLayersChild* shadowManager;
-  if (mUseAcceleratedRendering) {
-    shadowManager = mCompositorChild->SendPLayersConstructor(LayerManager::LAYERS_OPENGL, 0, &maxTextureSize);
-  } else {
-    shadowManager = mCompositorChild->SendPLayersConstructor(LayerManager::LAYERS_BASIC, 0, &maxTextureSize);
-  }
+  LayerManager::LayersBackend backendHint =
+    mUseAcceleratedRendering ? LayerManager::LAYERS_OPENGL : LayerManager::LAYERS_BASIC;
+  LayerManager::LayersBackend parentBackend;
+  shadowManager = mCompositorChild->SendPLayersConstructor(
+    backendHint, 0, &parentBackend, &maxTextureSize);
 
   if (shadowManager) {
     ShadowLayerForwarder* lf = lm->AsShadowForwarder();
     if (!lf) {
       delete lm;
       mCompositorChild = nsnull;
       return;
     }
     lf->SetShadowManager(shadowManager);
-    if (mUseAcceleratedRendering)
-      lf->SetParentBackendType(LayerManager::LAYERS_OPENGL);
-    else
-      lf->SetParentBackendType(LayerManager::LAYERS_BASIC);
+    lf->SetParentBackendType(parentBackend);
     lf->SetMaxTextureSize(maxTextureSize);
 
     mLayerManager = lm;
   } else {
     // We don't currently want to support not having a LayersChild
     NS_RUNTIMEABORT("failed to construct LayersChild");
     delete lm;
     mCompositorChild = nsnull;