Bug 861727. Refactor CompositorParent a bit. r=BenWa
authorNicholas Cameron <ncameron@mozilla.com>
Sun, 28 Apr 2013 18:46:30 +1200
changeset 130189 fad7e0541873fe43c0369cfbe7fb4e23f2798e08
parent 130188 d6de91faf60a1be9cc01bda2767371ed9554f257
child 130190 dc6bd7ea66f62a20583c4c9d09fc0c1441ee65df
push idunknown
push userunknown
push dateunknown
reviewersBenWa
bugs861727
milestone23.0a1
Bug 861727. Refactor CompositorParent a bit. r=BenWa
gfx/layers/Makefile.in
gfx/layers/composite/AsyncCompositionManager.cpp
gfx/layers/composite/AsyncCompositionManager.h
gfx/layers/ipc/AsyncPanZoomController.cpp
gfx/layers/ipc/CompositorParent.cpp
gfx/layers/ipc/CompositorParent.h
gfx/layers/ipc/ImageBridgeChild.cpp
gfx/layers/ipc/ImageBridgeParent.cpp
gfx/layers/moz.build
layout/ipc/RenderFrameParent.cpp
widget/android/nsWindow.cpp
--- a/gfx/layers/Makefile.in
+++ b/gfx/layers/Makefile.in
@@ -92,16 +92,17 @@ CPPSRCS += \
         ReadbackManagerD3D10.cpp \
         ShadowLayerUtilsD3D10.cpp \
         ThebesLayerD3D10.cpp \
         $(NULL)
 endif
 endif
 
 CPPSRCS += \
+        AsyncCompositionManager.cpp \
         AsyncPanZoomController.cpp \
         Axis.cpp \
         CanvasClient.cpp \
         CompositableClient.cpp \
         Compositor.cpp \
         CompositorOGL.cpp \
         CompositorCocoaWidgetHelper.cpp \
         CompositorChild.cpp \
copy from gfx/layers/ipc/CompositorParent.cpp
copy to gfx/layers/composite/AsyncCompositionManager.cpp
--- a/gfx/layers/ipc/CompositorParent.cpp
+++ b/gfx/layers/composite/AsyncCompositionManager.cpp
@@ -1,623 +1,140 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set sw=2 ts=2 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 <map>
-
-#include "mozilla/DebugOnly.h"
-
+#include "mozilla/layers/AsyncCompositionManager.h"
 #include "base/basictypes.h"
-#include <algorithm>
 
 #if defined(MOZ_WIDGET_ANDROID)
 # include <android/log.h>
 # include "AndroidBridge.h"
 #endif
 
-#include "AsyncPanZoomController.h"
-#include "AutoOpenSurface.h"
-#include "BasicLayers.h"
 #include "CompositorParent.h"
-#include "mozilla/layers/CompositorOGL.h"
-#include "nsGkAtoms.h"
-#include "nsIWidget.h"
-#include "RenderTrace.h"
-#include "LayerTransactionParent.h"
-#include "BasicLayers.h"
-#include "nsIWidget.h"
-#include "nsGkAtoms.h"
-#include "RenderTrace.h"
+#include "LayerManagerComposite.h" 
+
 #include "nsStyleAnimation.h"
 #include "nsDisplayList.h"
 #include "AnimationCommon.h"
 #include "nsAnimationManager.h"
-#include "gfxPlatform.h"
-#include "mozilla/dom/ScreenOrientation.h"
-#include "mozilla/AutoRestore.h"
+#include "mozilla/layers/AsyncPanZoomController.h"
 
-using namespace base;
-using namespace mozilla;
-using namespace mozilla::ipc;
 using namespace mozilla::dom;
-using namespace std;
 
 namespace mozilla {
 namespace layers {
 
-// FIXME/bug 774386: we're assuming that there's only one
-// CompositorParent, but that's not always true.  This assumption only
-// affects CrossProcessCompositorParent below.
-static CompositorParent* sCurrentCompositor;
-static Thread* sCompositorThread = nullptr;
-// manual reference count of the compositor thread.
-static int sCompositorThreadRefCount = 0;
-static MessageLoop* sMainLoop = nullptr;
-// When ContentParent::StartUp() is called, we use the Thread global.
-// When StartUpWithExistingThread() is used, we have to use the two
-// duplicated globals, because there's no API to make a Thread from an
-// existing thread.
-static PlatformThreadId sCompositorThreadID = 0;
-static MessageLoop* sCompositorLoop = nullptr;
-
-struct LayerTreeState {
-  nsRefPtr<Layer> mRoot;
-  nsRefPtr<AsyncPanZoomController> mController;
-  TargetConfig mTargetConfig;
-};
-
-/**
- * Lookup the indirect shadow tree for |aId| and return it if it
- * exists.  Otherwise null is returned.  This must only be called on
- * the compositor thread.
- */
-static const LayerTreeState* GetIndirectShadowTree(uint64_t aId);
-
-static void DeferredDeleteCompositorParent(CompositorParent* aNowReadyToDie)
-{
-  aNowReadyToDie->Release();
-}
-
-static void DeleteCompositorThread()
-{
-  if (NS_IsMainThread()){
-    delete sCompositorThread;
-    sCompositorThread = nullptr;
-    sCompositorLoop = nullptr;
-    sCompositorThreadID = 0;
-  } else {
-    sMainLoop->PostTask(FROM_HERE, NewRunnableFunction(&DeleteCompositorThread));
-  }
-}
-
-static void ReleaseCompositorThread()
-{
-  if(--sCompositorThreadRefCount == 0) {
-    DeleteCompositorThread();
-  }
-}
-
 void
-CompositorParent::StartUpWithExistingThread(MessageLoop* aMsgLoop,
-                                            PlatformThreadId aThreadID)
-{
-  MOZ_ASSERT(!sCompositorThread);
-  CreateCompositorMap();
-  sCompositorLoop = aMsgLoop;
-  sCompositorThreadID = aThreadID;
-  sMainLoop = MessageLoop::current();
-  sCompositorThreadRefCount = 1;
-}
-
-void CompositorParent::StartUp()
-{
-  // Check if compositor started already with StartUpWithExistingThread
-  if (sCompositorThreadID) {
-    return;
-  }
-  MOZ_ASSERT(!sCompositorLoop);
-  CreateCompositorMap();
-  CreateThread();
-  sMainLoop = MessageLoop::current();
-}
-
-void CompositorParent::ShutDown()
-{
-  DestroyThread();
-  DestroyCompositorMap();
-}
-
-bool CompositorParent::CreateThread()
-{
-  NS_ASSERTION(NS_IsMainThread(), "Should be on the main Thread!");
-  if (sCompositorThread || sCompositorLoop) {
-    return true;
-  }
-  sCompositorThreadRefCount = 1;
-  sCompositorThread = new Thread("Compositor");
-  if (!sCompositorThread->Start()) {
-    delete sCompositorThread;
-    sCompositorThread = nullptr;
-    return false;
-  }
-  return true;
-}
-
-void CompositorParent::DestroyThread()
-{
-  NS_ASSERTION(NS_IsMainThread(), "Should be on the main Thread!");
-  ReleaseCompositorThread();
-}
-
-MessageLoop* CompositorParent::CompositorLoop()
-{
-  return sCompositorThread ? sCompositorThread->message_loop() : sCompositorLoop;
-}
-
-CompositorParent::CompositorParent(nsIWidget* aWidget,
-                                   bool aRenderToEGLSurface,
-                                   int aSurfaceWidth, int aSurfaceHeight)
-  : mWidget(aWidget)
-  , mCurrentCompositeTask(NULL)
-  , mPaused(false)
-  , mXScale(1.0)
-  , mYScale(1.0)
-  , mIsFirstPaint(false)
-  , mLayersUpdated(false)
-  , mRenderToEGLSurface(aRenderToEGLSurface)
-  , mEGLSurfaceSize(aSurfaceWidth, aSurfaceHeight)
-  , mPauseCompositionMonitor("PauseCompositionMonitor")
-  , mResumeCompositionMonitor("ResumeCompositionMonitor")
-  , mOverrideComposeReadiness(false)
-  , mForceCompositionTask(nullptr)
-{
-  NS_ABORT_IF_FALSE(sCompositorThread != nullptr || sCompositorThreadID,
-                    "The compositor thread must be Initialized before instanciating a COmpositorParent.");
-  MOZ_COUNT_CTOR(CompositorParent);
-  mCompositorID = 0;
-  // FIXME: This holds on the the fact that right now the only thing that
-  // can destroy this instance is initialized on the compositor thread after
-  // this task has been processed.
-  CompositorLoop()->PostTask(FROM_HERE, NewRunnableFunction(&AddCompositor,
-                                                          this, &mCompositorID));
-
-  if (!sCurrentCompositor) {
-    sCurrentCompositor = this;
-  }
-  ++sCompositorThreadRefCount;
-}
-
-PlatformThreadId
-CompositorParent::CompositorThreadID()
-{
-  return sCompositorThread ? sCompositorThread->thread_id() : sCompositorThreadID;
-}
-
-CompositorParent::~CompositorParent()
-{
-  MOZ_COUNT_DTOR(CompositorParent);
-
-  if (this == sCurrentCompositor) {
-    sCurrentCompositor = NULL;
-  }
-  ReleaseCompositorThread();
-}
-
-void
-CompositorParent::Destroy()
-{
-  NS_ABORT_IF_FALSE(ManagedPLayerTransactionParent().Length() == 0,
-                    "CompositorParent destroyed before managed PLayerTransactionParent");
-
-  // Ensure that the layer manager is destructed on the compositor thread.
-  mLayerManager = NULL;
-}
-
-bool
-CompositorParent::RecvWillStop()
-{
-  mPaused = true;
-  RemoveCompositor(mCompositorID);
-
-  // Ensure that the layer manager is destroyed before CompositorChild.
-  if (mLayerManager) {
-    mLayerManager->Destroy();
-  }
-
-  return true;
-}
-
-bool
-CompositorParent::RecvStop()
-{
-  Destroy();
-  // There are chances that the ref count reaches zero on the main thread shortly
-  // after this function returns while some ipdl code still needs to run on
-  // this thread.
-  // We must keep the compositor parent alive untill the code handling message
-  // reception is finished on this thread.
-  this->AddRef(); // Corresponds to DeferredDeleteCompositorParent's Release
-  CompositorLoop()->PostTask(FROM_HERE,
-                           NewRunnableFunction(&DeferredDeleteCompositorParent,
-                                               this));
-  return true;
-}
-
-bool
-CompositorParent::RecvPause()
-{
-  PauseComposition();
-  return true;
-}
-
-bool
-CompositorParent::RecvResume()
-{
-  ResumeComposition();
-  return true;
-}
-
-bool
-CompositorParent::RecvMakeSnapshot(const SurfaceDescriptor& aInSnapshot,
-                                   SurfaceDescriptor* aOutSnapshot)
-{
-  AutoOpenSurface opener(OPEN_READ_WRITE, aInSnapshot);
-  nsRefPtr<gfxContext> target = new gfxContext(opener.Get());
-  ComposeToTarget(target);
-  *aOutSnapshot = aInSnapshot;
-  return true;
-}
-
-void
-CompositorParent::ActorDestroy(ActorDestroyReason why)
-{
-  mPaused = true;
-  RemoveCompositor(mCompositorID);
-
-  if (mLayerManager) {
-    mLayerManager->Destroy();
-  }
-}
-
-
-void
-CompositorParent::ScheduleRenderOnCompositorThread()
-{
-  CancelableTask *renderTask = NewRunnableMethod(this, &CompositorParent::ScheduleComposition);
-  CompositorLoop()->PostTask(FROM_HERE, renderTask);
-}
-
-void
-CompositorParent::PauseComposition()
-{
-  NS_ABORT_IF_FALSE(CompositorThreadID() == PlatformThread::CurrentId(),
-                    "PauseComposition() can only be called on the compositor thread");
-
-  MonitorAutoLock lock(mPauseCompositionMonitor);
-
-  if (!mPaused) {
-    mPaused = true;
-
-    mLayerManager->GetCompositor()->Pause();
-  }
-
-  // if anyone's waiting to make sure that composition really got paused, tell them
-  lock.NotifyAll();
-}
-
-void
-CompositorParent::ResumeComposition()
-{
-  NS_ABORT_IF_FALSE(CompositorThreadID() == PlatformThread::CurrentId(),
-                    "ResumeComposition() can only be called on the compositor thread");
-
-  MonitorAutoLock lock(mResumeCompositionMonitor);
-
-  if (!mLayerManager->GetCompositor()->Resume()) {
-#ifdef MOZ_WIDGET_ANDROID
-    // We can't get a surface. This could be because the activity changed between
-    // the time resume was scheduled and now.
-    __android_log_print(ANDROID_LOG_INFO, "CompositorParent", "Unable to renew compositor surface; remaining in paused state");
-#endif
-    lock.NotifyAll();
-    return;
-  }
-
-  mPaused = false;
-
-  Composite();
-
-  // if anyone's waiting to make sure that composition really got resumed, tell them
-  lock.NotifyAll();
-}
-
-void
-CompositorParent::ForceComposition()
-{
-  // Cancel the orientation changed state to force composition
-  mForceCompositionTask = nullptr;
-  ScheduleRenderOnCompositorThread();
-}
-
-void
-CompositorParent::SetEGLSurfaceSize(int width, int height)
-{
-  NS_ASSERTION(mRenderToEGLSurface, "Compositor created without RenderToEGLSurface provided");
-  mEGLSurfaceSize.SizeTo(width, height);
-  if (mLayerManager) {
-    mLayerManager->GetCompositor()->SetDestinationSurfaceSize(gfx::IntSize(mEGLSurfaceSize.width, mEGLSurfaceSize.height));
-  }
-}
-
-void
-CompositorParent::ResumeCompositionAndResize(int width, int height)
-{
-  SetEGLSurfaceSize(width, height);
-  ResumeComposition();
-}
-
-/*
- * This will execute a pause synchronously, waiting to make sure that the compositor
- * really is paused.
- */
-void
-CompositorParent::SchedulePauseOnCompositorThread()
-{
-  MonitorAutoLock lock(mPauseCompositionMonitor);
-
-  CancelableTask *pauseTask = NewRunnableMethod(this,
-                                                &CompositorParent::PauseComposition);
-  CompositorLoop()->PostTask(FROM_HERE, pauseTask);
-
-  // Wait until the pause has actually been processed by the compositor thread
-  lock.Wait();
-}
-
-bool
-CompositorParent::ScheduleResumeOnCompositorThread(int width, int height)
-{
-  MonitorAutoLock lock(mResumeCompositionMonitor);
-
-  CancelableTask *resumeTask =
-    NewRunnableMethod(this, &CompositorParent::ResumeCompositionAndResize, width, height);
-  CompositorLoop()->PostTask(FROM_HERE, resumeTask);
-
-  // Wait until the resume has actually been processed by the compositor thread
-  lock.Wait();
-
-  return !mPaused;
-}
-
-void
-CompositorParent::ScheduleTask(CancelableTask* task, int time)
-{
-  if (time == 0) {
-    MessageLoop::current()->PostTask(FROM_HERE, task);
-  } else {
-    MessageLoop::current()->PostDelayedTask(FROM_HERE, task, time);
-  }
-}
-
-void
-CompositorParent::NotifyShadowTreeTransaction()
-{
-  if (mLayerManager) {
-    LayerManagerComposite* managerComposite = mLayerManager->AsLayerManagerComposite();
-    if (managerComposite) {
-      managerComposite->NotifyShadowTreeTransaction();
-    }
-  }
-  ScheduleComposition();
-}
-
-void
-CompositorParent::ScheduleComposition()
-{
-  if (mCurrentCompositeTask) {
-    return;
-  }
-
-  bool initialComposition = mLastCompose.IsNull();
-  TimeDuration delta;
-  if (!initialComposition)
-    delta = TimeStamp::Now() - mLastCompose;
-
-#ifdef COMPOSITOR_PERFORMANCE_WARNING
-  mExpectedComposeTime = TimeStamp::Now() + TimeDuration::FromMilliseconds(15);
-#endif
-
-  mCurrentCompositeTask = NewRunnableMethod(this, &CompositorParent::Composite);
-
-  // Since 60 fps is the maximum frame rate we can acheive, scheduling composition
-  // events less than 15 ms apart wastes computation..
-  if (!initialComposition && delta.ToMilliseconds() < 15) {
-#ifdef COMPOSITOR_PERFORMANCE_WARNING
-    mExpectedComposeTime = TimeStamp::Now() + TimeDuration::FromMilliseconds(15 - delta.ToMilliseconds());
-#endif
-    ScheduleTask(mCurrentCompositeTask, 15 - delta.ToMilliseconds());
-  } else {
-    ScheduleTask(mCurrentCompositeTask, 0);
-  }
-}
-
-void
-CompositorParent::SetTransformation(float aScale, nsIntPoint aScrollOffset)
+AsyncCompositionManager::SetTransformation(float aScale,
+                                           const nsIntPoint& aScrollOffset)
 {
   mXScale = aScale;
   mYScale = aScale;
   mScrollOffset = aScrollOffset;
 }
 
-/**
- * DRAWING PHASE ONLY
- *
- * For reach RefLayer in |aRoot|, look up its referent and connect it
- * to the layer tree, if found.  On exiting scope, detaches all
- * resolved referents.
- */
-class MOZ_STACK_CLASS AutoResolveRefLayers {
-public:
-  /**
-   * |aRoot| must remain valid in the scope of this, which should be
-   * guaranteed by this helper only being used during the drawing
-   * phase.
-   */
-  AutoResolveRefLayers(Layer* aRoot, const TargetConfig& aConfig) : mRoot(aRoot), mTargetConfig(aConfig), mReadyForCompose(true)
-  { WalkTheTree<Resolve>(mRoot, nullptr); }
+enum Op { Resolve, Detach };
 
-  ~AutoResolveRefLayers()
-  { WalkTheTree<Detach>(mRoot, nullptr); }
+static bool
+IsSameDimension(ScreenOrientation o1, ScreenOrientation o2)
+{
+  bool isO1portrait = (o1 == eScreenOrientation_PortraitPrimary || o1 == eScreenOrientation_PortraitSecondary);
+  bool isO2portrait = (o2 == eScreenOrientation_PortraitPrimary || o2 == eScreenOrientation_PortraitSecondary);
+  return !(isO1portrait ^ isO2portrait);
+}
 
-  bool IsReadyForCompose()
-  { return mReadyForCompose; }
+static bool
+ContentMightReflowOnOrientationChange(const nsIntRect& rect)
+{
+  return rect.width != rect.height;
+}
 
-private:
-  enum Op { Resolve, Detach };
-  template<Op OP>
-  void WalkTheTree(Layer* aLayer, Layer* aParent)
-  {
-    if (RefLayer* ref = aLayer->AsRefLayer()) {
-      if (const LayerTreeState* state = GetIndirectShadowTree(ref->GetReferentId())) {
-        if (Layer* referent = state->mRoot) {
-          if (!ref->GetVisibleRegion().IsEmpty()) {
-            ScreenOrientation chromeOrientation = mTargetConfig.orientation();
-            ScreenOrientation contentOrientation = state->mTargetConfig.orientation();
-            if (!IsSameDimension(chromeOrientation, contentOrientation) &&
-                ContentMightReflowOnOrientationChange(mTargetConfig.clientBounds())) {
-              mReadyForCompose = false;
-            }
+template<Op OP>
+static void
+WalkTheTree(Layer* aLayer,
+            Layer* aParent,
+            bool& aReady,
+            const TargetConfig& aTargetConfig)
+{
+  if (RefLayer* ref = aLayer->AsRefLayer()) {
+    if (const CompositorParent::LayerTreeState* state = CompositorParent::GetIndirectShadowTree(ref->GetReferentId())) {
+      if (Layer* referent = state->mRoot) {
+        if (!ref->GetVisibleRegion().IsEmpty()) {
+          ScreenOrientation chromeOrientation = aTargetConfig.orientation();
+          ScreenOrientation contentOrientation = state->mTargetConfig.orientation();
+          if (!IsSameDimension(chromeOrientation, contentOrientation) &&
+              ContentMightReflowOnOrientationChange(aTargetConfig.clientBounds())) {
+            aReady = false;
           }
+        }
 
-          if (OP == Resolve) {
-            ref->ConnectReferentLayer(referent);
-            if (AsyncPanZoomController* apzc = state->mController) {
-              referent->SetAsyncPanZoomController(apzc);
-            }
-          } else {
-            ref->DetachReferentLayer(referent);
-            referent->SetAsyncPanZoomController(nullptr);
+        if (OP == Resolve) {
+          ref->ConnectReferentLayer(referent);
+          if (AsyncPanZoomController* apzc = state->mController) {
+            referent->SetAsyncPanZoomController(apzc);
           }
+        } else {
+          ref->DetachReferentLayer(referent);
+          referent->SetAsyncPanZoomController(nullptr);
         }
       }
     }
-    for (Layer* child = aLayer->GetFirstChild();
-         child; child = child->GetNextSibling()) {
-      WalkTheTree<OP>(child, aLayer);
-    }
-  }
-
-  bool IsSameDimension(ScreenOrientation o1, ScreenOrientation o2) {
-    bool isO1portrait = (o1 == eScreenOrientation_PortraitPrimary || o1 == eScreenOrientation_PortraitSecondary);
-    bool isO2portrait = (o2 == eScreenOrientation_PortraitPrimary || o2 == eScreenOrientation_PortraitSecondary);
-    return !(isO1portrait ^ isO2portrait);
   }
-
-  bool ContentMightReflowOnOrientationChange(nsIntRect& rect) {
-    return rect.width != rect.height;
+  for (Layer* child = aLayer->GetFirstChild();
+       child; child = child->GetNextSibling()) {
+    WalkTheTree<OP>(child, aLayer, aReady, aTargetConfig);
   }
-
-  Layer* mRoot;
-  TargetConfig mTargetConfig;
-  bool mReadyForCompose;
-
-  AutoResolveRefLayers(const AutoResolveRefLayers&) MOZ_DELETE;
-  AutoResolveRefLayers& operator=(const AutoResolveRefLayers&) MOZ_DELETE;
-};
+}
 
 void
-CompositorParent::Composite()
+AsyncCompositionManager::ResolveRefLayers()
 {
-  NS_ABORT_IF_FALSE(CompositorThreadID() == PlatformThread::CurrentId(),
-                    "Composite can only be called on the compositor thread");
-  mCurrentCompositeTask = nullptr;
-
-  mLastCompose = TimeStamp::Now();
-
-  if (!CanComposite()) {
-    return;
-  }
+  WalkTheTree<Resolve>(mLayerManager->GetRoot(),
+                       nullptr,
+                       mReadyForCompose,
+                       mTargetConfig);
+}
 
-  Layer* layer = mLayerManager->GetRoot();
-  AutoResolveRefLayers resolve(layer, mTargetConfig);
-  if (mForceCompositionTask && !mOverrideComposeReadiness) {
-    if (!resolve.IsReadyForCompose()) {
-      return;
-    } else {
-      mForceCompositionTask->Cancel();
-      mForceCompositionTask = nullptr;
-    }
-  }
+void
+AsyncCompositionManager::DetachRefLayers()
+{
+  WalkTheTree<Detach>(mLayerManager->GetRoot(),
+                      nullptr,
+                      mReadyForCompose,
+                      mTargetConfig);
+}
 
-  bool requestNextFrame = TransformShadowTree(mLastCompose);
-  if (requestNextFrame) {
-    ScheduleComposition();
-  }
-
-  RenderTraceLayers(layer, "0000");
-
+void
+AsyncCompositionManager::ComputeRotation()
+{
   if (!mTargetConfig.naturalBounds().IsEmpty()) {
     mLayerManager->SetWorldTransform(
       ComputeTransformForRotation(mTargetConfig.naturalBounds(),
                                   mTargetConfig.rotation()));
   }
-#ifdef MOZ_DUMP_PAINTING
-  static bool gDumpCompositorTree = false;
-  if (gDumpCompositorTree) {
-    fprintf(stdout, "Painting --- compositing layer tree:\n");
-    mLayerManager->Dump(stdout, "", false);
-  }
-#endif
-  mLayerManager->EndEmptyTransaction();
-
-#ifdef COMPOSITOR_PERFORMANCE_WARNING
-  if (mExpectedComposeTime + TimeDuration::FromMilliseconds(15) < TimeStamp::Now()) {
-    printf_stderr("Compositor: Composite took %i ms.\n",
-                  15 + (int)(TimeStamp::Now() - mExpectedComposeTime).ToMilliseconds());
-  }
-#endif
-}
-
-void
-CompositorParent::ComposeToTarget(gfxContext* aTarget)
-{
-  AutoRestore<bool> override(mOverrideComposeReadiness);
-  mOverrideComposeReadiness = true;
-
-  if (!CanComposite()) {
-    return;
-  }
-  mLayerManager->BeginTransactionWithTarget(aTarget);
-  // Since CanComposite() is true, Composite() must end the layers txn
-  // we opened above.
-  Composite();
-}
-
-bool
-CompositorParent::CanComposite()
-{
-  return !(mPaused || !mLayerManager || !mLayerManager->GetRoot());
 }
 
 // Do a breadth-first search to find the first layer in the tree that is
 // scrollable.
 static void
 Translate2D(gfx3DMatrix& aTransform, const gfxPoint& aOffset)
 {
   aTransform._41 += aOffset.x;
   aTransform._42 += aOffset.y;
 }
 
 void
-CompositorParent::TransformFixedLayers(Layer* aLayer,
-                                       const gfxPoint& aTranslation,
-                                       const gfxSize& aScaleDiff,
-                                       const gfx::Margin& aFixedLayerMargins)
+AsyncCompositionManager::TransformFixedLayers(Layer* aLayer,
+                                              const gfxPoint& aTranslation,
+                                              const gfxSize& aScaleDiff,
+                                              const gfx::Margin& aFixedLayerMargins)
 {
   if (aLayer->GetIsFixedPosition() &&
       !aLayer->GetParent()->GetIsFixedPosition()) {
     // When a scale has been applied to a layer, it focuses around (0,0).
     // The anchor position is used here as a scale focus point (assuming that
     // aScaleDiff has already been applied) to re-focus the scale.
     const gfxPoint& anchor = aLayer->GetFixedPositionAnchor();
     gfxPoint translation(aTranslation - (anchor - anchor / aScaleDiff));
@@ -678,35 +195,16 @@ CompositorParent::TransformFixedLayers(L
   }
 
   for (Layer* child = aLayer->GetFirstChild();
        child; child = child->GetNextSibling()) {
     TransformFixedLayers(child, aTranslation, aScaleDiff, aFixedLayerMargins);
   }
 }
 
-// Go down the composite layer tree, setting properties to match their
-// content-side counterparts.
-static void
-SetShadowProperties(Layer* aLayer)
-{
-  // FIXME: Bug 717688 -- Do these updates in LayerTransactionParent::RecvUpdate.
-  LayerComposite* layerComposite = aLayer->AsLayerComposite();
-  // Set the layerComposite's base transform to the layer's base transform.
-  layerComposite->SetShadowTransform(aLayer->GetBaseTransform());
-  layerComposite->SetShadowVisibleRegion(aLayer->GetVisibleRegion());
-  layerComposite->SetShadowClipRect(aLayer->GetClipRect());
-  layerComposite->SetShadowOpacity(aLayer->GetOpacity());
-
-  for (Layer* child = aLayer->GetFirstChild();
-      child; child = child->GetNextSibling()) {
-    SetShadowProperties(child);
-  }
-}
-
 static void
 SampleValue(float aPortion, Animation& aAnimation, nsStyleAnimation::Value& aStart,
             nsStyleAnimation::Value& aEnd, Animatable* aValue)
 {
   nsStyleAnimation::Value interpolatedValue;
   NS_ASSERTION(aStart.GetUnit() == aEnd.GetUnit() ||
                aStart.GetUnit() == nsStyleAnimation::eUnit_None ||
                aEnd.GetUnit() == nsStyleAnimation::eUnit_None, "Must have same unit");
@@ -821,19 +319,19 @@ SampleAnimations(Layer* aLayer, TimeStam
        child = child->GetNextSibling()) {
     activeAnimations |= SampleAnimations(child, aPoint);
   }
 
   return activeAnimations;
 }
 
 bool
-CompositorParent::ApplyAsyncContentTransformToTree(TimeStamp aCurrentFrame,
-                                                   Layer *aLayer,
-                                                   bool* aWantNextFrame)
+AsyncCompositionManager::ApplyAsyncContentTransformToTree(TimeStamp aCurrentFrame,
+                                                          Layer *aLayer,
+                                                          bool* aWantNextFrame)
 {
   bool appliedTransform = false;
   for (Layer* child = aLayer->GetFirstChild();
       child; child = child->GetNextSibling()) {
     appliedTransform |=
       ApplyAsyncContentTransformToTree(aCurrentFrame, child, aWantNextFrame);
   }
 
@@ -883,17 +381,17 @@ CompositorParent::ApplyAsyncContentTrans
 
     appliedTransform = true;
   }
 
   return appliedTransform;
 }
 
 void
-CompositorParent::TransformScrollableLayer(Layer* aLayer, const gfx3DMatrix& aRootTransform)
+AsyncCompositionManager::TransformScrollableLayer(Layer* aLayer, const gfx3DMatrix& aRootTransform)
 {
   LayerComposite* layerComposite = aLayer->AsLayerComposite();
   ContainerLayer* container = aLayer->AsContainerLayer();
 
   const FrameMetrics& metrics = container->GetFrameMetrics();
   // We must apply the resolution scale before a pan/zoom transform, so we call
   // GetTransform here.
   const gfx3DMatrix& currentTransform = aLayer->GetTransform();
@@ -1007,17 +505,17 @@ CompositorParent::TransformScrollableLay
   computedTransform.ScalePost(1.0f/container->GetPostXScale(),
                               1.0f/container->GetPostYScale(),
                               1);
   layerComposite->SetShadowTransform(computedTransform);
   TransformFixedLayers(aLayer, offset, scaleDiff, fixedLayerMargins);
 }
 
 bool
-CompositorParent::TransformShadowTree(TimeStamp aCurrentFrame)
+AsyncCompositionManager::TransformShadowTree(TimeStamp aCurrentFrame)
 {
   bool wantNextFrame = false;
   Layer* root = mLayerManager->GetRoot();
 
   // NB: we must sample animations *before* sampling pan/zoom
   // transforms.
   wantNextFrame |= SampleAnimations(root, aCurrentFrame);
 
@@ -1048,392 +546,48 @@ CompositorParent::TransformShadowTree(Ti
       }
     }
   }
 
   return wantNextFrame;
 }
 
 void
-CompositorParent::ShadowLayersUpdated(LayerTransactionParent* aLayerTree,
-                                      const TargetConfig& aTargetConfig,
-                                      bool isFirstPaint)
-{
-  if (!isFirstPaint && !mIsFirstPaint && mTargetConfig.orientation() != aTargetConfig.orientation()) {
-    if (mForceCompositionTask != NULL) {
-      mForceCompositionTask->Cancel();
-    }
-    mForceCompositionTask = NewRunnableMethod(this, &CompositorParent::ForceComposition);
-    ScheduleTask(mForceCompositionTask, gfxPlatform::GetPlatform()->GetOrientationSyncMillis());
-  }
-
-  // Instruct the LayerManager to update its render bounds now. Since all the orientation
-  // change, dimension change would be done at the stage, update the size here is free of
-  // race condition.
-  mLayerManager->UpdateRenderBounds(aTargetConfig.clientBounds());
-
-  mTargetConfig = aTargetConfig;
-  mIsFirstPaint = mIsFirstPaint || isFirstPaint;
-  mLayersUpdated = true;
-  Layer* root = aLayerTree->GetRoot();
-  mLayerManager->SetRoot(root);
-  if (root) {
-    SetShadowProperties(root);
-  }
-  ScheduleComposition();
-  LayerManagerComposite *layerComposite = mLayerManager->AsLayerManagerComposite();
-  if (layerComposite) {
-    layerComposite->NotifyShadowTreeTransaction();
-  }
-}
-
-
-void
-CompositorParent::SetFirstPaintViewport(const nsIntPoint& aOffset, float aZoom,
-                                        const nsIntRect& aPageRect, const gfx::Rect& aCssPageRect)
+AsyncCompositionManager::SetFirstPaintViewport(const nsIntPoint& aOffset,
+                                               float aZoom,
+                                               const nsIntRect& aPageRect,
+                                               const gfx::Rect& aCssPageRect)
 {
 #ifdef MOZ_WIDGET_ANDROID
   AndroidBridge::Bridge()->SetFirstPaintViewport(aOffset, aZoom, aPageRect, aCssPageRect);
 #endif
 }
 
 void
-CompositorParent::SetPageRect(const gfx::Rect& aCssPageRect)
+AsyncCompositionManager::SetPageRect(const gfx::Rect& aCssPageRect)
 {
 #ifdef MOZ_WIDGET_ANDROID
   AndroidBridge::Bridge()->SetPageRect(aCssPageRect);
 #endif
 }
 
 void
-CompositorParent::SyncViewportInfo(const nsIntRect& aDisplayPort,
-                                   float aDisplayResolution, bool aLayersUpdated,
-                                   nsIntPoint& aScrollOffset, float& aScaleX, float& aScaleY,
-                                   gfx::Margin& aFixedLayerMargins, float& aOffsetX,
-                                   float& aOffsetY)
+AsyncCompositionManager::SyncViewportInfo(const nsIntRect& aDisplayPort,
+                                          float aDisplayResolution,
+                                          bool aLayersUpdated,
+                                          nsIntPoint& aScrollOffset,
+                                          float& aScaleX, float& aScaleY,
+                                          gfx::Margin& aFixedLayerMargins,
+                                          float& aOffsetX, float& aOffsetY)
 {
 #ifdef MOZ_WIDGET_ANDROID
-  AndroidBridge::Bridge()->SyncViewportInfo(aDisplayPort, aDisplayResolution, aLayersUpdated,
-                                            aScrollOffset, aScaleX, aScaleY, aFixedLayerMargins,
+  AndroidBridge::Bridge()->SyncViewportInfo(aDisplayPort,
+                                            aDisplayResolution,
+                                            aLayersUpdated,
+                                            aScrollOffset,
+                                            aScaleX, aScaleY,
+                                            aFixedLayerMargins,
                                             aOffsetX, aOffsetY);
 #endif
 }
 
-PLayerTransactionParent*
-CompositorParent::AllocPLayerTransaction(const LayersBackend& aBackendHint,
-                                         const uint64_t& aId,
-                                         TextureFactoryIdentifier* aTextureFactoryIdentifier)
-{
-  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->GetClientBounds(rect);
-
-  if (aBackendHint == mozilla::layers::LAYERS_OPENGL) {
-    mLayerManager =
-      new LayerManagerComposite(new CompositorOGL(mWidget,
-                                                  mEGLSurfaceSize.width,
-                                                  mEGLSurfaceSize.height,
-                                                  mRenderToEGLSurface));
-    mWidget = nullptr;
-    mLayerManager->SetCompositorID(mCompositorID);
-
-    if (!mLayerManager->Initialize()) {
-      NS_ERROR("Failed to init Compositor");
-      return NULL;
-    }
-
-    *aTextureFactoryIdentifier = mLayerManager->GetTextureFactoryIdentifier();
-    return new LayerTransactionParent(mLayerManager, this, 0);
-  // Basic layers compositor not yet implemented
-  /*} else if (aBackendHint == mozilla::layers::LAYERS_BASIC) {
-    nsRefPtr<LayerManager> layerManager = new BasicShadowLayerManager(mWidget);
-    mWidget = NULL;
-    mLayerManager = layerManager;
-    LayerManagerComposite* slm = layerManager->AsLayerManagerComposite();
-    if (!slm) {
-      return NULL;
-    }
-    *aTextureFactoryIdentifier = layerManager->GetTextureFactoryIdentifier();
-    return new LayerTransactionParent(slm, this, 0); */
-  } else {
-    NS_ERROR("Unsupported backend selected for Async Compositor");
-    return NULL;
-  }
-}
-
-bool
-CompositorParent::DeallocPLayerTransaction(PLayerTransactionParent* actor)
-{
-  delete actor;
-  return true;
-}
-
-
-typedef map<uint64_t,CompositorParent*> CompositorMap;
-static CompositorMap* sCompositorMap;
-
-void CompositorParent::CreateCompositorMap()
-{
-  if (sCompositorMap == nullptr) {
-    sCompositorMap = new CompositorMap;
-  }
-}
-
-void CompositorParent::DestroyCompositorMap()
-{
-  if (sCompositorMap != nullptr) {
-    NS_ASSERTION(sCompositorMap->empty(),
-                 "The Compositor map should be empty when destroyed>");
-    delete sCompositorMap;
-    sCompositorMap = nullptr;
-  }
-}
-
-CompositorParent* CompositorParent::GetCompositor(uint64_t id)
-{
-  CompositorMap::iterator it = sCompositorMap->find(id);
-  return it != sCompositorMap->end() ? it->second : nullptr;
-}
-
-void CompositorParent::AddCompositor(CompositorParent* compositor, uint64_t* outID)
-{
-  static uint64_t sNextID = 1;
-
-  ++sNextID;
-  (*sCompositorMap)[sNextID] = compositor;
-  *outID = sNextID;
-}
-
-CompositorParent* CompositorParent::RemoveCompositor(uint64_t id)
-{
-  CompositorMap::iterator it = sCompositorMap->find(id);
-  if (it == sCompositorMap->end()) {
-    return nullptr;
-  }
-  CompositorParent *retval = it->second;
-  sCompositorMap->erase(it);
-  return retval;
-}
-
-typedef map<uint64_t, LayerTreeState> LayerTreeMap;
-static LayerTreeMap sIndirectLayerTrees;
-
-/*static*/ uint64_t
-CompositorParent::AllocateLayerTreeId()
-{
-  MOZ_ASSERT(CompositorLoop());
-  MOZ_ASSERT(NS_IsMainThread());
-  static uint64_t ids;
-  return ++ids;
-}
-
-static void
-EraseLayerState(uint64_t aId)
-{
-  sIndirectLayerTrees.erase(aId);
-}
-
-/*static*/ void
-CompositorParent::DeallocateLayerTreeId(uint64_t aId)
-{
-  MOZ_ASSERT(NS_IsMainThread());
-  CompositorLoop()->PostTask(FROM_HERE,
-                             NewRunnableFunction(&EraseLayerState, aId));
-}
-
-static void
-UpdateControllerForLayersId(uint64_t aLayersId,
-                            AsyncPanZoomController* aController)
-{
-  // Adopt ref given to us by SetPanZoomControllerForLayerTree()
-  sIndirectLayerTrees[aLayersId].mController =
-    already_AddRefed<AsyncPanZoomController>(aController);
-
-  // Notify the AsyncPanZoomController about the current compositor so that it
-  // can request composites off the compositor thread.
-  aController->SetCompositorParent(sCurrentCompositor);
-}
-
-/*static*/ void
-CompositorParent::SetPanZoomControllerForLayerTree(uint64_t aLayersId,
-                                                   AsyncPanZoomController* aController)
-{
-  // This ref is adopted by UpdateControllerForLayersId().
-  aController->AddRef();
-  CompositorLoop()->PostTask(FROM_HERE,
-                             NewRunnableFunction(&UpdateControllerForLayersId,
-                                                 aLayersId,
-                                                 aController));
-}
-
-/**
- * This class handles layer updates pushed directly from child
- * processes to the compositor thread.  It's associated with a
- * CompositorParent on the compositor thread.  While it uses the
- * PCompositor protocol to manage these updates, it doesn't actually
- * drive compositing itself.  For that it hands off work to the
- * CompositorParent it's associated with.
- */
-class CrossProcessCompositorParent : public PCompositorParent,
-                                     public ShadowLayersManager
-{
-  friend class CompositorParent;
-
-  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CrossProcessCompositorParent)
-public:
-  CrossProcessCompositorParent(Transport* aTransport)
-    : mTransport(aTransport)
-  {}
-  virtual ~CrossProcessCompositorParent();
-
-  virtual void ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
-
-  // 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 bool RecvMakeSnapshot(const SurfaceDescriptor& aInSnapshot,
-                                SurfaceDescriptor* aOutSnapshot)
-  { return true; }
-
-  virtual PLayerTransactionParent*
-    AllocPLayerTransaction(const LayersBackend& aBackendType,
-                           const uint64_t& aId,
-                           TextureFactoryIdentifier* aTextureFactoryIdentifier) MOZ_OVERRIDE;
-
-  virtual bool DeallocPLayerTransaction(PLayerTransactionParent* aLayers) MOZ_OVERRIDE;
-
-  virtual void ShadowLayersUpdated(LayerTransactionParent* aLayerTree,
-                                   const TargetConfig& aTargetConfig,
-                                   bool isFirstPaint) MOZ_OVERRIDE;
-
-private:
-  void DeferredDestroy();
-
-  // There can be many CPCPs, and IPDL-generated code doesn't hold a
-  // reference to top-level actors.  So we hold a reference to
-  // ourself.  This is released (deferred) in ActorDestroy().
-  nsRefPtr<CrossProcessCompositorParent> mSelfRef;
-  Transport* mTransport;
-};
-
-static void
-OpenCompositor(CrossProcessCompositorParent* aCompositor,
-               Transport* aTransport, ProcessHandle aHandle,
-               MessageLoop* aIOLoop)
-{
-  DebugOnly<bool> ok = aCompositor->Open(aTransport, aHandle, aIOLoop);
-  MOZ_ASSERT(ok);
-}
-
-/*static*/ PCompositorParent*
-CompositorParent::Create(Transport* aTransport, ProcessId aOtherProcess)
-{
-  nsRefPtr<CrossProcessCompositorParent> cpcp =
-    new CrossProcessCompositorParent(aTransport);
-  ProcessHandle handle;
-  if (!base::OpenProcessHandle(aOtherProcess, &handle)) {
-    // XXX need to kill |aOtherProcess|, it's boned
-    return nullptr;
-  }
-  cpcp->mSelfRef = cpcp;
-  CompositorLoop()->PostTask(
-    FROM_HERE,
-    NewRunnableFunction(OpenCompositor, cpcp.get(),
-                        aTransport, handle, XRE_GetIOMessageLoop()));
-  // The return value is just compared to null for success checking,
-  // we're not sharing a ref.
-  return cpcp.get();
-}
-
-static void
-UpdateIndirectTree(uint64_t aId, Layer* aRoot, const TargetConfig& aTargetConfig, bool isFirstPaint)
-{
-  sIndirectLayerTrees[aId].mRoot = aRoot;
-  sIndirectLayerTrees[aId].mTargetConfig = aTargetConfig;
-  if (ContainerLayer* root = aRoot->AsContainerLayer()) {
-    if (AsyncPanZoomController* apzc = sIndirectLayerTrees[aId].mController) {
-      apzc->NotifyLayersUpdated(root->GetFrameMetrics(), isFirstPaint);
-    }
-  }
-}
-
-static const LayerTreeState*
-GetIndirectShadowTree(uint64_t aId)
-{
-  LayerTreeMap::const_iterator cit = sIndirectLayerTrees.find(aId);
-  if (sIndirectLayerTrees.end() == cit) {
-    return nullptr;
-  }
-  return &cit->second;
-}
-
-static void
-RemoveIndirectTree(uint64_t aId)
-{
-  sIndirectLayerTrees.erase(aId);
-}
-
-void
-CrossProcessCompositorParent::ActorDestroy(ActorDestroyReason aWhy)
-{
-  MessageLoop::current()->PostTask(
-    FROM_HERE,
-    NewRunnableMethod(this, &CrossProcessCompositorParent::DeferredDestroy));
-}
-
-PLayerTransactionParent*
-CrossProcessCompositorParent::AllocPLayerTransaction(const LayersBackend& aBackendType,
-                                                     const uint64_t& aId,
-                                                     TextureFactoryIdentifier* aTextureFactoryIdentifier)
-{
-  MOZ_ASSERT(aId != 0);
-
-  nsRefPtr<LayerManager> lm = sCurrentCompositor->GetLayerManager();
-  *aTextureFactoryIdentifier = lm->GetTextureFactoryIdentifier();
-  return new LayerTransactionParent(lm->AsLayerManagerComposite(), this, aId);
-}
-
-bool
-CrossProcessCompositorParent::DeallocPLayerTransaction(PLayerTransactionParent* aLayers)
-{
-  LayerTransactionParent* slp = static_cast<LayerTransactionParent*>(aLayers);
-  RemoveIndirectTree(slp->GetId());
-  delete aLayers;
-  return true;
-}
-
-void
-CrossProcessCompositorParent::ShadowLayersUpdated(
-  LayerTransactionParent* aLayerTree,
-  const TargetConfig& aTargetConfig,
-  bool isFirstPaint)
-{
-  uint64_t id = aLayerTree->GetId();
-  MOZ_ASSERT(id != 0);
-  Layer* shadowRoot = aLayerTree->GetRoot();
-  if (shadowRoot) {
-    SetShadowProperties(shadowRoot);
-  }
-  UpdateIndirectTree(id, shadowRoot, aTargetConfig, isFirstPaint);
-
-  sCurrentCompositor->NotifyShadowTreeTransaction();
-}
-
-void
-CrossProcessCompositorParent::DeferredDestroy()
-{
-  mSelfRef = nullptr;
-  // |this| was just destroyed, hands off
-}
-
-CrossProcessCompositorParent::~CrossProcessCompositorParent()
-{
-  XRE_GetIOMessageLoop()->PostTask(FROM_HERE,
-                                   new DeleteTask<Transport>(mTransport));
-}
-
 } // namespace layers
 } // namespace mozilla
copy from gfx/layers/ipc/CompositorParent.h
copy to gfx/layers/composite/AsyncCompositionManager.h
--- a/gfx/layers/ipc/CompositorParent.h
+++ b/gfx/layers/composite/AsyncCompositionManager.h
@@ -1,45 +1,33 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set sw=4 ts=8 et tw=80 : */
-/* This Source Code Form is subject to the terms of the Mozilla Public
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * 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/. */
 
-#ifndef mozilla_layers_CompositorParent_h
-#define mozilla_layers_CompositorParent_h
-
-// Enable this pref to turn on compositor performance warning.
-// This will print warnings if the compositor isn't meeting
-// its responsiveness objectives:
-//    1) Compose a frame within 15ms of receiving a ScheduleCompositeCall
-//    2) Unless a frame was composited within the throttle threshold in
-//       which the deadline will be 15ms + throttle threshold
-//#define COMPOSITOR_PERFORMANCE_WARNING
+#ifndef GFX_ASYNCCOMPOSITIONMANAGER_H
+#define GFX_ASYNCCOMPOSITIONMANAGER_H
 
-#include "mozilla/layers/PCompositorParent.h"
-#include "mozilla/layers/PLayerTransactionParent.h"
-#include "base/thread.h"
-#include "mozilla/Monitor.h"
+#include "gfxPoint.h"
+#include "gfx3DMatrix.h"
+#include "nsAutoPtr.h"
+#include "nsRect.h"
+#include "mozilla/dom/ScreenOrientation.h"
+#include "mozilla/gfx/Rect.h"
+#include "mozilla/RefPtr.h"
 #include "mozilla/TimeStamp.h"
-#include "ShadowLayersManager.h"
-#include "mozilla/layers/LayerManagerComposite.h"
-class nsIWidget;
-
-namespace base {
-class Thread;
-}
+#include "mozilla/layers/LayerTransaction.h" // for TargetConfig
 
 namespace mozilla {
 namespace layers {
 
 class AsyncPanZoomController;
 class Layer;
-class LayerManager;
-struct TextureFactoryIdentifier;
+class LayerManagerComposite;
+class AutoResolveRefLayers;
 
 // Represents (affine) transforms that are calculated from a content view.
 struct ViewTransform {
   ViewTransform(gfxPoint aTranslation = gfxPoint(),
                 gfxSize aScale = gfxSize(1, 1))
     : mTranslation(aTranslation)
     , mScale(aScale)
   {}
@@ -50,262 +38,166 @@ struct ViewTransform {
       gfx3DMatrix::ScalingMatrix(mScale.width, mScale.height, 1) *
       gfx3DMatrix::Translation(mTranslation.x, mTranslation.y, 0);
   }
 
   gfxPoint mTranslation;
   gfxSize mScale;
 };
 
-class CompositorParent : public PCompositorParent,
-                         public ShadowLayersManager
+/**
+ * Manage async composition effects. This class is only used with OMTC and only
+ * lives on the compositor thread. It is a layer on top of the layer manager
+ * (LayerManagerComposite) which deals with elements of composition which are
+ * usually dealt with by dom or layout when main thread rendering, but which can
+ * short circuit that stuff to directly affect layers as they are composited,
+ * for example, off-main thread animation, async video, async pan/zoom.
+ */
+class AsyncCompositionManager : public RefCounted<AsyncCompositionManager>
 {
-  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CompositorParent)
-
+  friend class AutoResolveRefLayers;
 public:
-  CompositorParent(nsIWidget* aWidget,
-                   bool aRenderToEGLSurface = false,
-                   int aSurfaceWidth = -1, int aSurfaceHeight = -1);
-
-  virtual ~CompositorParent();
+  AsyncCompositionManager(LayerManagerComposite* aManager)
+    : mXScale(1.0)
+    , mYScale(1.0)
+    , mLayerManager(aManager)
+    , mIsFirstPaint(false)
+    , mLayersUpdated(false)
+    , mReadyForCompose(true)
+  {
+    MOZ_COUNT_CTOR(AsyncCompositionManager);
+  }
+  ~AsyncCompositionManager()
+  {
+    MOZ_COUNT_DTOR(AsyncCompositionManager);
+  }
 
-  virtual bool RecvWillStop() MOZ_OVERRIDE;
-  virtual bool RecvStop() MOZ_OVERRIDE;
-  virtual bool RecvPause() MOZ_OVERRIDE;
-  virtual bool RecvResume() MOZ_OVERRIDE;
-  virtual bool RecvMakeSnapshot(const SurfaceDescriptor& aInSnapshot,
-                                SurfaceDescriptor* aOutSnapshot);
-
-  virtual void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE;
-
-  virtual void ShadowLayersUpdated(LayerTransactionParent* aLayerTree,
-                                   const TargetConfig& aTargetConfig,
-                                   bool isFirstPaint) MOZ_OVERRIDE;
   /**
    * This forces the is-first-paint flag to true. This is intended to
    * be called by the widget code when it loses its viewport information
    * (or for whatever reason wants to refresh the viewport information).
    * The information refresh happens because the compositor will call
    * SetFirstPaintViewport on the next frame of composition.
    */
   void ForceIsFirstPaint() { mIsFirstPaint = true; }
-  void Destroy();
-
-  LayerManagerComposite* GetLayerManager() { return mLayerManager; }
-
-  void SetTransformation(float aScale, nsIntPoint aScrollOffset);
-  void AsyncRender();
-
-  // Can be called from any thread
-  void ScheduleRenderOnCompositorThread();
-  void SchedulePauseOnCompositorThread();
-  /**
-   * Returns true if a surface was obtained and the resume succeeded; false
-   * otherwise.
-   */
-  bool ScheduleResumeOnCompositorThread(int width, int height);
-
-  virtual void ScheduleComposition();
-  void NotifyShadowTreeTransaction();
-
-  /**
-   * Returns a pointer to the compositor corresponding to the given ID.
-   */
-  static CompositorParent* GetCompositor(uint64_t id);
-
-  /**
-   * Returns the compositor thread's message loop.
-   *
-   * This message loop is used by CompositorParent and ImageBridgeParent.
-   */
-  static MessageLoop* CompositorLoop();
-
-  /**
-   * Creates the compositor thread and the global compositor map.
-   */
-  static void StartUp();
-
-  /**
-   * Destroys the compositor thread and the global compositor map.
-   */
-  static void ShutDown();
-
-  /**
-   * Allocate an ID that can be used to refer to a layer tree and
-   * associated resources that live only on the compositor thread.
-   *
-   * Must run on the content main thread.
-   */
-  static uint64_t AllocateLayerTreeId();
-  /**
-   * Release compositor-thread resources referred to by |aID|.
-   *
-   * Must run on the content main thread.
-   */
-  static void DeallocateLayerTreeId(uint64_t aId);
-
-  /**
-   * Set aController as the pan/zoom controller for the tree referred
-   * to by aLayersId.
-   *
-   * Must run on content main thread.
-   */
-  static void SetPanZoomControllerForLayerTree(uint64_t aLayersId,
-                                               AsyncPanZoomController* aController);
-
-  /**
-   * 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);
-
-  /**
-   * Setup external message loop and thread ID for Compositor.
-   * Should be used when CompositorParent should work in existing thread/MessageLoop,
-   * for example moving Compositor into native toolkit main thread will allow to avoid
-   * extra synchronization and call ::Composite() right from toolkit::Paint event
-   */
-  static void StartUpWithExistingThread(MessageLoop* aMsgLoop,
-                                        PlatformThreadId aThreadID);
-
-protected:
-  virtual PLayerTransactionParent*
-    AllocPLayerTransaction(const LayersBackend& aBackendHint,
-                           const uint64_t& aId,
-                           TextureFactoryIdentifier* aTextureFactoryIdentifier);
-  virtual bool DeallocPLayerTransaction(PLayerTransactionParent* aLayers);
-  virtual void ScheduleTask(CancelableTask*, int);
-  virtual void Composite();
-  virtual void ComposeToTarget(gfxContext* aTarget);
-  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,
-                                gfx::Margin& aFixedLayerMargins, float& aOffsetX, float& aOffsetY);
-  virtual void SyncFrameMetrics(Layer* aLayer, const ViewTransform& aTreeTransform,
-                                const gfxPoint& aScrollOffset, gfx::Margin& aFixedLayerMargins,
-                                float& aOffsetX, float& aOffsetY,
-                                bool aIsFirstPaint, bool aLayersUpdated) {
-  }
-
-  void SetEGLSurfaceSize(int width, int height);
-
-private:
-  void PauseComposition();
-  void ResumeComposition();
-  void ResumeCompositionAndResize(int width, int height);
-  void ForceComposition();
 
   // Sample transforms for layer trees.  Return true to request
   // another animation frame.
   bool TransformShadowTree(TimeStamp aCurrentFrame);
+
+  // Calculates the correct rotation and applies the transform to
+  // our layer manager
+  void ComputeRotation();
+
+  // Call after updating our layer tree.
+  void Updated(bool isFirstPaint, const TargetConfig& aTargetConfig)
+  {
+    mIsFirstPaint |= isFirstPaint;
+    mLayersUpdated = true;
+    mTargetConfig = aTargetConfig;
+  }
+
+  bool RequiresReorientation(mozilla::dom::ScreenOrientation aOrientation)
+  {
+    return mTargetConfig.orientation() != aOrientation;
+  }
+
+  // True if the underlying layer tree is ready to be composited.
+  bool ReadyForCompose() { return mReadyForCompose; }
+
+  // Returns true if the next composition will be the first for a
+  // particular document.
+  bool IsFirstPaint() { return mIsFirstPaint; }
+
+  void SetTransformation(float aScale, const nsIntPoint& aScrollOffset);
+
+private:
   void TransformScrollableLayer(Layer* aLayer, const gfx3DMatrix& aRootTransform);
   // Return true if an AsyncPanZoomController content transform was
   // applied for |aLayer|.  *aWantNextFrame is set to true if the
   // controller wants another animation frame.
   bool ApplyAsyncContentTransformToTree(TimeStamp aCurrentFrame, Layer* aLayer,
                                         bool* aWantNextFrame);
 
-  inline PlatformThreadId CompositorThreadID();
-
-  /**
-   * Creates a global map referencing each compositor by ID.
-   *
-   * This map is used by the ImageBridge protocol to trigger
-   * compositions without having to keep references to the
-   * compositor
-   */
-  static void CreateCompositorMap();
-  static void DestroyCompositorMap();
-
-  /**
-   * Creates the compositor thread.
-   *
-   * All compositors live on the same thread.
-   * The thread is not lazily created on first access to avoid dealing with
-   * thread safety. Therefore it's best to create and destroy the thread when
-   * we know we areb't using it (So creating/destroying along with gfxPlatform
-   * looks like a good place).
-   */
-  static bool CreateThread();
+  void SetFirstPaintViewport(const nsIntPoint& aOffset,
+                             float aZoom,
+                             const nsIntRect& aPageRect,
+                             const gfx::Rect& aCssPageRect);
+  void SetPageRect(const gfx::Rect& aCssPageRect);
+  void SyncViewportInfo(const nsIntRect& aDisplayPort,
+                        float aDisplayResolution,
+                        bool aLayersUpdated,
+                        nsIntPoint& aScrollOffset,
+                        float& aScaleX, float& aScaleY,
+                        gfx::Margin& aFixedLayerMargins,
+                        float& aOffsetX, float& aOffsetY);
+  virtual void SyncFrameMetrics(Layer* aLayer, const ViewTransform& aTreeTransform,
+                                const gfxPoint& aScrollOffset, gfx::Margin& aFixedLayerMargins,
+                                float& aOffsetX, float& aOffsetY,
+                                bool aIsFirstPaint, bool aLayersUpdated)
+  {}
 
   /**
-   * Destroys the compositor thread.
-   *
-   * It is safe to call this fucntion more than once, although the second call
-   * will have no effect.
-   * This function is not thread-safe.
-   */
-  static void DestroyThread();
-
-  /**
-   * Add a compositor to the global compositor map.
-   */
-  static void AddCompositor(CompositorParent* compositor, uint64_t* id);
-  /**
-   * Remove a compositor from the global compositor map.
-   */
-  static CompositorParent* RemoveCompositor(uint64_t id);
-
-   /**
-   * Return true if current state allows compositing, that is
-   * finishing a layers transaction.
-   */
-  bool CanComposite();
-
-  // Platform specific functions
-  /**
    * Recursively applies the given translation to all top-level fixed position
    * layers that are descendants of the given layer.
    * aScaleDiff is considered to be the scale transformation applied when
    * displaying the layers, and is used to make sure the anchor points of
    * fixed position layers remain in the same position.
    */
   void TransformFixedLayers(Layer* aLayer,
                             const gfxPoint& aTranslation,
                             const gfxSize& aScaleDiff,
                             const gfx::Margin& aFixedLayerMargins);
 
-  nsRefPtr<LayerManagerComposite> mLayerManager;
-  nsIWidget* mWidget;
+  /**
+   * DRAWING PHASE ONLY
+   *
+   * For reach RefLayer in our layer tree, look up its referent and connect it
+   * to the layer tree, if found.
+   */
+  void ResolveRefLayers();
+  /**
+   * Detaches all referents resolved by ResolveRefLayers.
+   * Assumes that mLayerManager->GetRoot() and mTargetConfig have not changed
+   * since ResolveRefLayers was called.
+   */
+  void DetachRefLayers();
+
   TargetConfig mTargetConfig;
-  CancelableTask *mCurrentCompositeTask;
-  TimeStamp mLastCompose;
-#ifdef COMPOSITOR_PERFORMANCE_WARNING
-  TimeStamp mExpectedComposeTime;
-#endif
-
-  bool mPaused;
   float mXScale;
   float mYScale;
   nsIntPoint mScrollOffset;
   nsIntRect mContentRect;
 
+  nsRefPtr<LayerManagerComposite> mLayerManager;
   // When this flag is set, the next composition will be the first for a
   // particular document (i.e. the document displayed on the screen will change).
   // This happens when loading a new page or switching tabs. We notify the
   // front-end (e.g. Java on Android) about this so that it take the new page
   // size and zoom into account when providing us with the next view transform.
   bool mIsFirstPaint;
 
   // This flag is set during a layers update, so that the first composition
   // after a layers update has it set. It is cleared after that first composition.
   bool mLayersUpdated;
 
-  bool mRenderToEGLSurface;
-  nsIntSize mEGLSurfaceSize;
+  bool mReadyForCompose;
+};
 
-  mozilla::Monitor mPauseCompositionMonitor;
-  mozilla::Monitor mResumeCompositionMonitor;
+class MOZ_STACK_CLASS AutoResolveRefLayers {
+public:
+  AutoResolveRefLayers(AsyncCompositionManager* aManager) : mManager(aManager)
+  { mManager->ResolveRefLayers(); }
 
-  uint64_t mCompositorID;
+  ~AutoResolveRefLayers()
+  { mManager->DetachRefLayers(); }
 
-  bool mOverrideComposeReadiness;
-  CancelableTask* mForceCompositionTask;
+private:
+  AsyncCompositionManager* mManager;
 
-  DISALLOW_EVIL_CONSTRUCTORS(CompositorParent);
+  AutoResolveRefLayers(const AutoResolveRefLayers&) MOZ_DELETE;
+  AutoResolveRefLayers& operator=(const AutoResolveRefLayers&) MOZ_DELETE;
 };
 
 } // layers
 } // mozilla
 
-#endif // mozilla_layers_CompositorParent_h
+#endif
--- a/gfx/layers/ipc/AsyncPanZoomController.cpp
+++ b/gfx/layers/ipc/AsyncPanZoomController.cpp
@@ -1,29 +1,31 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set sw=4 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 "mozilla/layers/AsyncCompositionManager.h" // for ViewTransform
 #include "CompositorParent.h"
 #include "mozilla/gfx/2D.h"
 #include "mozilla/ClearOnShutdown.h"
 #include "mozilla/Constants.h"
 #include "mozilla/Util.h"
 #include "mozilla/XPCOM.h"
 #include "mozilla/Monitor.h"
 #include "mozilla/StaticPtr.h"
 #include "AsyncPanZoomController.h"
 #include "GestureEventListener.h"
 #include "nsIThreadManager.h"
 #include "nsThreadUtils.h"
 #include "Layers.h"
 #include "AnimationCommon.h"
 #include <algorithm>
+#include "mozilla/layers/LayerManagerComposite.h"
 
 using namespace mozilla::css;
 
 namespace mozilla {
 namespace layers {
 
 /**
  * Constant describing the tolerance in distance we use, multiplied by the
--- a/gfx/layers/ipc/CompositorParent.cpp
+++ b/gfx/layers/ipc/CompositorParent.cpp
@@ -3,49 +3,32 @@
 /* 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 <map>
 
 #include "mozilla/DebugOnly.h"
 
-#include "base/basictypes.h"
-#include <algorithm>
-
-#if defined(MOZ_WIDGET_ANDROID)
-# include <android/log.h>
-# include "AndroidBridge.h"
-#endif
-
 #include "AsyncPanZoomController.h"
 #include "AutoOpenSurface.h"
-#include "BasicLayers.h"
 #include "CompositorParent.h"
 #include "mozilla/layers/CompositorOGL.h"
-#include "nsGkAtoms.h"
-#include "nsIWidget.h"
-#include "RenderTrace.h"
 #include "LayerTransactionParent.h"
-#include "BasicLayers.h"
 #include "nsIWidget.h"
 #include "nsGkAtoms.h"
 #include "RenderTrace.h"
-#include "nsStyleAnimation.h"
-#include "nsDisplayList.h"
-#include "AnimationCommon.h"
-#include "nsAnimationManager.h"
 #include "gfxPlatform.h"
-#include "mozilla/dom/ScreenOrientation.h"
 #include "mozilla/AutoRestore.h"
+#include "mozilla/layers/AsyncCompositionManager.h"
+#include "mozilla/layers/LayerManagerComposite.h"
 
 using namespace base;
 using namespace mozilla;
 using namespace mozilla::ipc;
-using namespace mozilla::dom;
 using namespace std;
 
 namespace mozilla {
 namespace layers {
 
 // FIXME/bug 774386: we're assuming that there's only one
 // CompositorParent, but that's not always true.  This assumption only
 // affects CrossProcessCompositorParent below.
@@ -56,29 +39,16 @@ static int sCompositorThreadRefCount = 0
 static MessageLoop* sMainLoop = nullptr;
 // When ContentParent::StartUp() is called, we use the Thread global.
 // When StartUpWithExistingThread() is used, we have to use the two
 // duplicated globals, because there's no API to make a Thread from an
 // existing thread.
 static PlatformThreadId sCompositorThreadID = 0;
 static MessageLoop* sCompositorLoop = nullptr;
 
-struct LayerTreeState {
-  nsRefPtr<Layer> mRoot;
-  nsRefPtr<AsyncPanZoomController> mController;
-  TargetConfig mTargetConfig;
-};
-
-/**
- * Lookup the indirect shadow tree for |aId| and return it if it
- * exists.  Otherwise null is returned.  This must only be called on
- * the compositor thread.
- */
-static const LayerTreeState* GetIndirectShadowTree(uint64_t aId);
-
 static void DeferredDeleteCompositorParent(CompositorParent* aNowReadyToDie)
 {
   aNowReadyToDie->Release();
 }
 
 static void DeleteCompositorThread()
 {
   if (NS_IsMainThread()){
@@ -156,20 +126,16 @@ MessageLoop* CompositorParent::Composito
 }
 
 CompositorParent::CompositorParent(nsIWidget* aWidget,
                                    bool aRenderToEGLSurface,
                                    int aSurfaceWidth, int aSurfaceHeight)
   : mWidget(aWidget)
   , mCurrentCompositeTask(NULL)
   , mPaused(false)
-  , mXScale(1.0)
-  , mYScale(1.0)
-  , mIsFirstPaint(false)
-  , mLayersUpdated(false)
   , mRenderToEGLSurface(aRenderToEGLSurface)
   , mEGLSurfaceSize(aSurfaceWidth, aSurfaceHeight)
   , mPauseCompositionMonitor("PauseCompositionMonitor")
   , mResumeCompositionMonitor("ResumeCompositionMonitor")
   , mOverrideComposeReadiness(false)
   , mForceCompositionTask(nullptr)
 {
   NS_ABORT_IF_FALSE(sCompositorThread != nullptr || sCompositorThreadID,
@@ -206,28 +172,37 @@ CompositorParent::~CompositorParent()
 
 void
 CompositorParent::Destroy()
 {
   NS_ABORT_IF_FALSE(ManagedPLayerTransactionParent().Length() == 0,
                     "CompositorParent destroyed before managed PLayerTransactionParent");
 
   // Ensure that the layer manager is destructed on the compositor thread.
-  mLayerManager = NULL;
+  mLayerManager = nullptr;
+  mCompositionManager = nullptr;
+}
+
+void
+CompositorParent::ForceIsFirstPaint()
+{
+  mCompositionManager->ForceIsFirstPaint();
 }
 
 bool
 CompositorParent::RecvWillStop()
 {
   mPaused = true;
   RemoveCompositor(mCompositorID);
 
   // Ensure that the layer manager is destroyed before CompositorChild.
   if (mLayerManager) {
     mLayerManager->Destroy();
+    mLayerManager = nullptr;
+    mCompositionManager = nullptr;
   }
 
   return true;
 }
 
 bool
 CompositorParent::RecvStop()
 {
@@ -272,16 +247,18 @@ CompositorParent::RecvMakeSnapshot(const
 void
 CompositorParent::ActorDestroy(ActorDestroyReason why)
 {
   mPaused = true;
   RemoveCompositor(mCompositorID);
 
   if (mLayerManager) {
     mLayerManager->Destroy();
+    mLayerManager = nullptr;
+    mCompositionManager = nullptr;
   }
 }
 
 
 void
 CompositorParent::ScheduleRenderOnCompositorThread()
 {
   CancelableTask *renderTask = NewRunnableMethod(this, &CompositorParent::ScheduleComposition);
@@ -439,133 +416,51 @@ CompositorParent::ScheduleComposition()
   } else {
     ScheduleTask(mCurrentCompositeTask, 0);
   }
 }
 
 void
 CompositorParent::SetTransformation(float aScale, nsIntPoint aScrollOffset)
 {
-  mXScale = aScale;
-  mYScale = aScale;
-  mScrollOffset = aScrollOffset;
+  mCompositionManager->SetTransformation(aScale, aScrollOffset);
 }
 
-/**
- * DRAWING PHASE ONLY
- *
- * For reach RefLayer in |aRoot|, look up its referent and connect it
- * to the layer tree, if found.  On exiting scope, detaches all
- * resolved referents.
- */
-class MOZ_STACK_CLASS AutoResolveRefLayers {
-public:
-  /**
-   * |aRoot| must remain valid in the scope of this, which should be
-   * guaranteed by this helper only being used during the drawing
-   * phase.
-   */
-  AutoResolveRefLayers(Layer* aRoot, const TargetConfig& aConfig) : mRoot(aRoot), mTargetConfig(aConfig), mReadyForCompose(true)
-  { WalkTheTree<Resolve>(mRoot, nullptr); }
-
-  ~AutoResolveRefLayers()
-  { WalkTheTree<Detach>(mRoot, nullptr); }
-
-  bool IsReadyForCompose()
-  { return mReadyForCompose; }
-
-private:
-  enum Op { Resolve, Detach };
-  template<Op OP>
-  void WalkTheTree(Layer* aLayer, Layer* aParent)
-  {
-    if (RefLayer* ref = aLayer->AsRefLayer()) {
-      if (const LayerTreeState* state = GetIndirectShadowTree(ref->GetReferentId())) {
-        if (Layer* referent = state->mRoot) {
-          if (!ref->GetVisibleRegion().IsEmpty()) {
-            ScreenOrientation chromeOrientation = mTargetConfig.orientation();
-            ScreenOrientation contentOrientation = state->mTargetConfig.orientation();
-            if (!IsSameDimension(chromeOrientation, contentOrientation) &&
-                ContentMightReflowOnOrientationChange(mTargetConfig.clientBounds())) {
-              mReadyForCompose = false;
-            }
-          }
-
-          if (OP == Resolve) {
-            ref->ConnectReferentLayer(referent);
-            if (AsyncPanZoomController* apzc = state->mController) {
-              referent->SetAsyncPanZoomController(apzc);
-            }
-          } else {
-            ref->DetachReferentLayer(referent);
-            referent->SetAsyncPanZoomController(nullptr);
-          }
-        }
-      }
-    }
-    for (Layer* child = aLayer->GetFirstChild();
-         child; child = child->GetNextSibling()) {
-      WalkTheTree<OP>(child, aLayer);
-    }
-  }
-
-  bool IsSameDimension(ScreenOrientation o1, ScreenOrientation o2) {
-    bool isO1portrait = (o1 == eScreenOrientation_PortraitPrimary || o1 == eScreenOrientation_PortraitSecondary);
-    bool isO2portrait = (o2 == eScreenOrientation_PortraitPrimary || o2 == eScreenOrientation_PortraitSecondary);
-    return !(isO1portrait ^ isO2portrait);
-  }
-
-  bool ContentMightReflowOnOrientationChange(nsIntRect& rect) {
-    return rect.width != rect.height;
-  }
-
-  Layer* mRoot;
-  TargetConfig mTargetConfig;
-  bool mReadyForCompose;
-
-  AutoResolveRefLayers(const AutoResolveRefLayers&) MOZ_DELETE;
-  AutoResolveRefLayers& operator=(const AutoResolveRefLayers&) MOZ_DELETE;
-};
-
 void
 CompositorParent::Composite()
 {
   NS_ABORT_IF_FALSE(CompositorThreadID() == PlatformThread::CurrentId(),
                     "Composite can only be called on the compositor thread");
   mCurrentCompositeTask = nullptr;
 
   mLastCompose = TimeStamp::Now();
 
   if (!CanComposite()) {
     return;
   }
 
-  Layer* layer = mLayerManager->GetRoot();
-  AutoResolveRefLayers resolve(layer, mTargetConfig);
+  AutoResolveRefLayers resolve(mCompositionManager);
   if (mForceCompositionTask && !mOverrideComposeReadiness) {
-    if (!resolve.IsReadyForCompose()) {
-      return;
-    } else {
+    if (mCompositionManager->ReadyForCompose()) {
       mForceCompositionTask->Cancel();
       mForceCompositionTask = nullptr;
+    } else {
+      return;
     }
   }
 
-  bool requestNextFrame = TransformShadowTree(mLastCompose);
+  bool requestNextFrame = mCompositionManager->TransformShadowTree(mLastCompose);
   if (requestNextFrame) {
     ScheduleComposition();
   }
 
-  RenderTraceLayers(layer, "0000");
+  RenderTraceLayers(mLayerManager->GetRoot(), "0000");
 
-  if (!mTargetConfig.naturalBounds().IsEmpty()) {
-    mLayerManager->SetWorldTransform(
-      ComputeTransformForRotation(mTargetConfig.naturalBounds(),
-                                  mTargetConfig.rotation()));
-  }
+  mCompositionManager->ComputeRotation();
+
 #ifdef MOZ_DUMP_PAINTING
   static bool gDumpCompositorTree = false;
   if (gDumpCompositorTree) {
     fprintf(stdout, "Painting --- compositing layer tree:\n");
     mLayerManager->Dump(stdout, "", false);
   }
 #endif
   mLayerManager->EndEmptyTransaction();
@@ -594,100 +489,16 @@ CompositorParent::ComposeToTarget(gfxCon
 }
 
 bool
 CompositorParent::CanComposite()
 {
   return !(mPaused || !mLayerManager || !mLayerManager->GetRoot());
 }
 
-// Do a breadth-first search to find the first layer in the tree that is
-// scrollable.
-static void
-Translate2D(gfx3DMatrix& aTransform, const gfxPoint& aOffset)
-{
-  aTransform._41 += aOffset.x;
-  aTransform._42 += aOffset.y;
-}
-
-void
-CompositorParent::TransformFixedLayers(Layer* aLayer,
-                                       const gfxPoint& aTranslation,
-                                       const gfxSize& aScaleDiff,
-                                       const gfx::Margin& aFixedLayerMargins)
-{
-  if (aLayer->GetIsFixedPosition() &&
-      !aLayer->GetParent()->GetIsFixedPosition()) {
-    // When a scale has been applied to a layer, it focuses around (0,0).
-    // The anchor position is used here as a scale focus point (assuming that
-    // aScaleDiff has already been applied) to re-focus the scale.
-    const gfxPoint& anchor = aLayer->GetFixedPositionAnchor();
-    gfxPoint translation(aTranslation - (anchor - anchor / aScaleDiff));
-
-    // Offset this translation by the fixed layer margins, depending on what
-    // side of the viewport the layer is anchored to, reconciling the
-    // difference between the current fixed layer margins and the Gecko-side
-    // fixed layer margins.
-    // aFixedLayerMargins are the margins we expect to be at at the current
-    // time, obtained via SyncViewportInfo, and fixedMargins are the margins
-    // that were used during layout.
-    // If top/left of fixedMargins are negative, that indicates that this layer
-    // represents auto-positioned elements, and should not be affected by
-    // fixed margins at all.
-    const gfx::Margin& fixedMargins = aLayer->GetFixedPositionMargins();
-    if (fixedMargins.left >= 0) {
-      if (anchor.x > 0) {
-        translation.x -= aFixedLayerMargins.right - fixedMargins.right;
-      } else {
-        translation.x += aFixedLayerMargins.left - fixedMargins.left;
-      }
-    }
-
-    if (fixedMargins.top >= 0) {
-      if (anchor.y > 0) {
-        translation.y -= aFixedLayerMargins.bottom - fixedMargins.bottom;
-      } else {
-        translation.y += aFixedLayerMargins.top - fixedMargins.top;
-      }
-    }
-
-    // The transform already takes the resolution scale into account.  Since we
-    // will apply the resolution scale again when computing the effective
-    // transform, we must apply the inverse resolution scale here.
-    gfx3DMatrix layerTransform = aLayer->GetTransform();
-    Translate2D(layerTransform, translation);
-    if (ContainerLayer* c = aLayer->AsContainerLayer()) {
-      layerTransform.Scale(1.0f/c->GetPreXScale(),
-                           1.0f/c->GetPreYScale(),
-                           1);
-    }
-    layerTransform.ScalePost(1.0f/aLayer->GetPostXScale(),
-                             1.0f/aLayer->GetPostYScale(),
-                             1);
-    LayerComposite* layerComposite = aLayer->AsLayerComposite();
-    layerComposite->SetShadowTransform(layerTransform);
-
-    const nsIntRect* clipRect = aLayer->GetClipRect();
-    if (clipRect) {
-      nsIntRect transformedClipRect(*clipRect);
-      transformedClipRect.MoveBy(translation.x, translation.y);
-      layerComposite->SetShadowClipRect(&transformedClipRect);
-    }
-
-    // The transform has now been applied, so there's no need to iterate over
-    // child layers.
-    return;
-  }
-
-  for (Layer* child = aLayer->GetFirstChild();
-       child; child = child->GetNextSibling()) {
-    TransformFixedLayers(child, aTranslation, aScaleDiff, aFixedLayerMargins);
-  }
-}
-
 // Go down the composite layer tree, setting properties to match their
 // content-side counterparts.
 static void
 SetShadowProperties(Layer* aLayer)
 {
   // FIXME: Bug 717688 -- Do these updates in LayerTransactionParent::RecvUpdate.
   LayerComposite* layerComposite = aLayer->AsLayerComposite();
   // Set the layerComposite's base transform to the layer's base transform.
@@ -697,473 +508,82 @@ SetShadowProperties(Layer* aLayer)
   layerComposite->SetShadowOpacity(aLayer->GetOpacity());
 
   for (Layer* child = aLayer->GetFirstChild();
       child; child = child->GetNextSibling()) {
     SetShadowProperties(child);
   }
 }
 
-static void
-SampleValue(float aPortion, Animation& aAnimation, nsStyleAnimation::Value& aStart,
-            nsStyleAnimation::Value& aEnd, Animatable* aValue)
-{
-  nsStyleAnimation::Value interpolatedValue;
-  NS_ASSERTION(aStart.GetUnit() == aEnd.GetUnit() ||
-               aStart.GetUnit() == nsStyleAnimation::eUnit_None ||
-               aEnd.GetUnit() == nsStyleAnimation::eUnit_None, "Must have same unit");
-  nsStyleAnimation::Interpolate(aAnimation.property(), aStart, aEnd,
-                                aPortion, interpolatedValue);
-  if (aAnimation.property() == eCSSProperty_opacity) {
-    *aValue = interpolatedValue.GetFloatValue();
-    return;
-  }
-
-  nsCSSValueList* interpolatedList = interpolatedValue.GetCSSValueListValue();
-
-  TransformData& data = aAnimation.data().get_TransformData();
-  nsPoint origin = data.origin();
-  // we expect all our transform data to arrive in css pixels, so here we must
-  // adjust to dev pixels.
-  double cssPerDev = double(nsDeviceContext::AppUnitsPerCSSPixel())
-                     / double(data.appUnitsPerDevPixel());
-  gfxPoint3D mozOrigin = data.mozOrigin();
-  mozOrigin.x = mozOrigin.x * cssPerDev;
-  mozOrigin.y = mozOrigin.y * cssPerDev;
-  gfxPoint3D perspectiveOrigin = data.perspectiveOrigin();
-  perspectiveOrigin.x = perspectiveOrigin.x * cssPerDev;
-  perspectiveOrigin.y = perspectiveOrigin.y * cssPerDev;
-  nsDisplayTransform::FrameTransformProperties props(interpolatedList,
-                                                     mozOrigin,
-                                                     perspectiveOrigin,
-                                                     data.perspective());
-  gfx3DMatrix transform =
-    nsDisplayTransform::GetResultingTransformMatrix(props, origin,
-                                                    data.appUnitsPerDevPixel(),
-                                                    &data.bounds());
-  gfxPoint3D scaledOrigin =
-    gfxPoint3D(NS_round(NSAppUnitsToFloatPixels(origin.x, data.appUnitsPerDevPixel())),
-               NS_round(NSAppUnitsToFloatPixels(origin.y, data.appUnitsPerDevPixel())),
-               0.0f);
-
-  transform.Translate(scaledOrigin);
-
-  InfallibleTArray<TransformFunction> functions;
-  functions.AppendElement(TransformMatrix(transform));
-  *aValue = functions;
-}
-
-static bool
-SampleAnimations(Layer* aLayer, TimeStamp aPoint)
-{
-  AnimationArray& animations = aLayer->GetAnimations();
-  InfallibleTArray<AnimData>& animationData = aLayer->GetAnimationData();
-
-  bool activeAnimations = false;
-
-  for (uint32_t i = animations.Length(); i-- !=0; ) {
-    Animation& animation = animations[i];
-    AnimData& animData = animationData[i];
-
-    double numIterations = animation.numIterations() != -1 ?
-      animation.numIterations() : NS_IEEEPositiveInfinity();
-    double positionInIteration =
-      ElementAnimations::GetPositionInIteration(aPoint - animation.startTime(),
-                                                animation.duration(),
-                                                numIterations,
-                                                animation.direction());
-
-    NS_ABORT_IF_FALSE(0.0 <= positionInIteration &&
-                      positionInIteration <= 1.0,
-                      "position should be in [0-1]");
-
-    int segmentIndex = 0;
-    AnimationSegment* segment = animation.segments().Elements();
-    while (segment->endPortion() < positionInIteration) {
-      ++segment;
-      ++segmentIndex;
-    }
-
-    double positionInSegment = (positionInIteration - segment->startPortion()) /
-                                 (segment->endPortion() - segment->startPortion());
-
-    double portion = animData.mFunctions[segmentIndex]->GetValue(positionInSegment);
-
-    activeAnimations = true;
-
-    // interpolate the property
-    Animatable interpolatedValue;
-    SampleValue(portion, animation, animData.mStartValues[segmentIndex],
-                animData.mEndValues[segmentIndex], &interpolatedValue);
-    LayerComposite* layerComposite = aLayer->AsLayerComposite();
-    switch (animation.property()) {
-    case eCSSProperty_opacity:
-    {
-      layerComposite->SetShadowOpacity(interpolatedValue.get_float());
-      break;
-    }
-    case eCSSProperty_transform:
-    {
-      gfx3DMatrix matrix = interpolatedValue.get_ArrayOfTransformFunction()[0].get_TransformMatrix().value();
-      if (ContainerLayer* c = aLayer->AsContainerLayer()) {
-        matrix.ScalePost(c->GetInheritedXScale(),
-                         c->GetInheritedYScale(),
-                         1);
-      }
-      NS_ASSERTION(!aLayer->GetIsFixedPosition(), "Can't animate transforms on fixed-position layers");
-      layerComposite->SetShadowTransform(matrix);
-      break;
-    }
-    default:
-      NS_WARNING("Unhandled animated property");
-    }
-  }
-
-  for (Layer* child = aLayer->GetFirstChild(); child;
-       child = child->GetNextSibling()) {
-    activeAnimations |= SampleAnimations(child, aPoint);
-  }
-
-  return activeAnimations;
-}
-
-bool
-CompositorParent::ApplyAsyncContentTransformToTree(TimeStamp aCurrentFrame,
-                                                   Layer *aLayer,
-                                                   bool* aWantNextFrame)
-{
-  bool appliedTransform = false;
-  for (Layer* child = aLayer->GetFirstChild();
-      child; child = child->GetNextSibling()) {
-    appliedTransform |=
-      ApplyAsyncContentTransformToTree(aCurrentFrame, child, aWantNextFrame);
-  }
-
-  ContainerLayer* container = aLayer->AsContainerLayer();
-  if (!container) {
-    return appliedTransform;
-  }
-
-  if (AsyncPanZoomController* controller = aLayer->GetAsyncPanZoomController()) {
-    LayerComposite* layerComposite = aLayer->AsLayerComposite();
-
-    ViewTransform treeTransform;
-    gfxPoint scrollOffset;
-    *aWantNextFrame |=
-      controller->SampleContentTransformForFrame(aCurrentFrame,
-                                                 container,
-                                                 &treeTransform,
-                                                 &scrollOffset);
-
-    gfx::Margin fixedLayerMargins(0, 0, 0, 0);
-    float offsetX = 0, offsetY = 0;
-    SyncFrameMetrics(aLayer, treeTransform, scrollOffset, fixedLayerMargins,
-                     offsetX, offsetY, mIsFirstPaint, mLayersUpdated);
-    mIsFirstPaint = false;
-    mLayersUpdated = false;
-
-    // Apply the render offset
-    mLayerManager->GetCompositor()->SetScreenRenderOffset(gfx::Point(offsetX, offsetY));
-
-    gfx3DMatrix transform(gfx3DMatrix(treeTransform) * aLayer->GetTransform());
-    // The transform already takes the resolution scale into account.  Since we
-    // will apply the resolution scale again when computing the effective
-    // transform, we must apply the inverse resolution scale here.
-    transform.Scale(1.0f/container->GetPreXScale(),
-                    1.0f/container->GetPreYScale(),
-                    1);
-    transform.ScalePost(1.0f/aLayer->GetPostXScale(),
-                        1.0f/aLayer->GetPostYScale(),
-                        1);
-    layerComposite->SetShadowTransform(transform);
-
-    TransformFixedLayers(
-      aLayer,
-      -treeTransform.mTranslation / treeTransform.mScale,
-      treeTransform.mScale,
-      fixedLayerMargins);
-
-    appliedTransform = true;
-  }
-
-  return appliedTransform;
-}
-
-void
-CompositorParent::TransformScrollableLayer(Layer* aLayer, const gfx3DMatrix& aRootTransform)
-{
-  LayerComposite* layerComposite = aLayer->AsLayerComposite();
-  ContainerLayer* container = aLayer->AsContainerLayer();
-
-  const FrameMetrics& metrics = container->GetFrameMetrics();
-  // We must apply the resolution scale before a pan/zoom transform, so we call
-  // GetTransform here.
-  const gfx3DMatrix& currentTransform = aLayer->GetTransform();
-
-  gfx3DMatrix treeTransform;
-
-  // Translate fixed position layers so that they stay in the correct position
-  // when mScrollOffset and metricsScrollOffset differ.
-  gfxPoint offset;
-  gfxSize scaleDiff;
-
-  float rootScaleX = aRootTransform.GetXScale(),
-        rootScaleY = aRootTransform.GetYScale();
-  // The ratio of layers pixels to device pixels.  The Java
-  // compositor wants to see values in units of device pixels, so we
-  // map our FrameMetrics values to that space.  This is not exposed
-  // as a FrameMetrics helper because it's a deprecated conversion.
-  float devPixelRatioX = 1 / rootScaleX, devPixelRatioY = 1 / rootScaleY;
-
-  gfxPoint scrollOffsetLayersPixels(metrics.GetScrollOffsetInLayerPixels());
-  nsIntPoint scrollOffsetDevPixels(
-    NS_lround(scrollOffsetLayersPixels.x * devPixelRatioX),
-    NS_lround(scrollOffsetLayersPixels.y * devPixelRatioY));
-
-  if (mIsFirstPaint) {
-    mContentRect = metrics.mContentRect;
-    SetFirstPaintViewport(scrollOffsetDevPixels,
-                          1/rootScaleX,
-                          mContentRect,
-                          metrics.mScrollableRect);
-    mIsFirstPaint = false;
-  } else if (!metrics.mContentRect.IsEqualEdges(mContentRect)) {
-    mContentRect = metrics.mContentRect;
-    SetPageRect(metrics.mScrollableRect);
-  }
-
-  // We synchronise the viewport information with Java after sending the above
-  // notifications, so that Java can take these into account in its response.
-  // Calculate the absolute display port to send to Java
-  gfx::Rect displayPortLayersPixels(metrics.mCriticalDisplayPort.IsEmpty() ?
-                                    metrics.mDisplayPort : metrics.mCriticalDisplayPort);
-  nsIntRect displayPortDevPixels(
-    NS_lround(displayPortLayersPixels.x * devPixelRatioX),
-    NS_lround(displayPortLayersPixels.y * devPixelRatioY),
-    NS_lround(displayPortLayersPixels.width * devPixelRatioX),
-    NS_lround(displayPortLayersPixels.height * devPixelRatioY));
-
-  displayPortDevPixels.x += scrollOffsetDevPixels.x;
-  displayPortDevPixels.y += scrollOffsetDevPixels.y;
-
-  gfx::Margin fixedLayerMargins(0, 0, 0, 0);
-  float offsetX = 0, offsetY = 0;
-  SyncViewportInfo(displayPortDevPixels, 1/rootScaleX, mLayersUpdated,
-                   mScrollOffset, mXScale, mYScale, fixedLayerMargins,
-                   offsetX, offsetY);
-  mLayersUpdated = false;
-
-  // Apply the render offset
-  mLayerManager->GetCompositor()->SetScreenRenderOffset(gfx::Point(offsetX, offsetY));
-
-  // Handle transformations for asynchronous panning and zooming. We determine the
-  // zoom used by Gecko from the transformation set on the root layer, and we
-  // determine the scroll offset used by Gecko from the frame metrics of the
-  // primary scrollable layer. We compare this to the desired zoom and scroll
-  // offset in the view transform we obtained from Java in order to compute the
-  // transformation we need to apply.
-  float tempScaleDiffX = rootScaleX * mXScale;
-  float tempScaleDiffY = rootScaleY * mYScale;
-
-  nsIntPoint metricsScrollOffset(0, 0);
-  if (metrics.IsScrollable()) {
-    metricsScrollOffset = scrollOffsetDevPixels;
-  }
-
-  nsIntPoint scrollCompensation(
-    (mScrollOffset.x / tempScaleDiffX - metricsScrollOffset.x) * mXScale,
-    (mScrollOffset.y / tempScaleDiffY - metricsScrollOffset.y) * mYScale);
-  treeTransform = gfx3DMatrix(ViewTransform(-scrollCompensation,
-                                            gfxSize(mXScale, mYScale)));
-
-  // If the contents can fit entirely within the widget area on a particular
-  // dimenson, we need to translate and scale so that the fixed layers remain
-  // within the page boundaries.
-  if (mContentRect.width * tempScaleDiffX < metrics.mCompositionBounds.width) {
-    offset.x = -metricsScrollOffset.x;
-    scaleDiff.width = std::min(1.0f, metrics.mCompositionBounds.width / (float)mContentRect.width);
-  } else {
-    offset.x = clamped(mScrollOffset.x / tempScaleDiffX, (float)mContentRect.x,
-                       mContentRect.XMost() - metrics.mCompositionBounds.width / tempScaleDiffX) -
-               metricsScrollOffset.x;
-    scaleDiff.width = tempScaleDiffX;
-  }
-
-  if (mContentRect.height * tempScaleDiffY < metrics.mCompositionBounds.height) {
-    offset.y = -metricsScrollOffset.y;
-    scaleDiff.height = std::min(1.0f, metrics.mCompositionBounds.height / (float)mContentRect.height);
-  } else {
-    offset.y = clamped(mScrollOffset.y / tempScaleDiffY, (float)mContentRect.y,
-                       mContentRect.YMost() - metrics.mCompositionBounds.height / tempScaleDiffY) -
-               metricsScrollOffset.y;
-    scaleDiff.height = tempScaleDiffY;
-  }
-
-  // The transform already takes the resolution scale into account.  Since we
-  // will apply the resolution scale again when computing the effective
-  // transform, we must apply the inverse resolution scale here.
-  gfx3DMatrix computedTransform = treeTransform * currentTransform;
-  computedTransform.Scale(1.0f/container->GetPreXScale(),
-                          1.0f/container->GetPreYScale(),
-                          1);
-  computedTransform.ScalePost(1.0f/container->GetPostXScale(),
-                              1.0f/container->GetPostYScale(),
-                              1);
-  layerComposite->SetShadowTransform(computedTransform);
-  TransformFixedLayers(aLayer, offset, scaleDiff, fixedLayerMargins);
-}
-
-bool
-CompositorParent::TransformShadowTree(TimeStamp aCurrentFrame)
-{
-  bool wantNextFrame = false;
-  Layer* root = mLayerManager->GetRoot();
-
-  // NB: we must sample animations *before* sampling pan/zoom
-  // transforms.
-  wantNextFrame |= SampleAnimations(root, aCurrentFrame);
-
-  const gfx3DMatrix& rootTransform = root->GetTransform();
-
-  // FIXME/bug 775437: unify this interface with the ~native-fennec
-  // derived code
-  //
-  // Attempt to apply an async content transform to any layer that has
-  // an async pan zoom controller (which means that it is rendered
-  // async using Gecko). If this fails, fall back to transforming the
-  // primary scrollable layer.  "Failing" here means that we don't
-  // find a frame that is async scrollable.  Note that the fallback
-  // code also includes Fennec which is rendered async.  Fennec uses
-  // its own platform-specific async rendering that is done partially
-  // in Gecko and partially in Java.
-  if (!ApplyAsyncContentTransformToTree(aCurrentFrame, root, &wantNextFrame)) {
-    nsAutoTArray<Layer*,1> scrollableLayers;
-#ifdef MOZ_WIDGET_ANDROID
-    scrollableLayers.AppendElement(mLayerManager->GetPrimaryScrollableLayer());
-#else
-    mLayerManager->GetScrollableLayers(scrollableLayers);
-#endif
-
-    for (uint32_t i = 0; i < scrollableLayers.Length(); i++) {
-      if (scrollableLayers[i]) {
-        TransformScrollableLayer(scrollableLayers[i], rootTransform);
-      }
-    }
-  }
-
-  return wantNextFrame;
-}
-
 void
 CompositorParent::ShadowLayersUpdated(LayerTransactionParent* aLayerTree,
                                       const TargetConfig& aTargetConfig,
                                       bool isFirstPaint)
 {
-  if (!isFirstPaint && !mIsFirstPaint && mTargetConfig.orientation() != aTargetConfig.orientation()) {
+  if (!isFirstPaint &&
+      !mCompositionManager->IsFirstPaint() &&
+      mCompositionManager->RequiresReorientation(aTargetConfig.orientation())) {
     if (mForceCompositionTask != NULL) {
       mForceCompositionTask->Cancel();
     }
     mForceCompositionTask = NewRunnableMethod(this, &CompositorParent::ForceComposition);
     ScheduleTask(mForceCompositionTask, gfxPlatform::GetPlatform()->GetOrientationSyncMillis());
   }
 
   // Instruct the LayerManager to update its render bounds now. Since all the orientation
   // change, dimension change would be done at the stage, update the size here is free of
   // race condition.
   mLayerManager->UpdateRenderBounds(aTargetConfig.clientBounds());
 
-  mTargetConfig = aTargetConfig;
-  mIsFirstPaint = mIsFirstPaint || isFirstPaint;
-  mLayersUpdated = true;
+  mCompositionManager->Updated(isFirstPaint, aTargetConfig);
   Layer* root = aLayerTree->GetRoot();
   mLayerManager->SetRoot(root);
   if (root) {
     SetShadowProperties(root);
   }
   ScheduleComposition();
   LayerManagerComposite *layerComposite = mLayerManager->AsLayerManagerComposite();
   if (layerComposite) {
     layerComposite->NotifyShadowTreeTransaction();
   }
 }
 
-
-void
-CompositorParent::SetFirstPaintViewport(const nsIntPoint& aOffset, float aZoom,
-                                        const nsIntRect& aPageRect, const gfx::Rect& aCssPageRect)
-{
-#ifdef MOZ_WIDGET_ANDROID
-  AndroidBridge::Bridge()->SetFirstPaintViewport(aOffset, aZoom, aPageRect, aCssPageRect);
-#endif
-}
-
-void
-CompositorParent::SetPageRect(const gfx::Rect& aCssPageRect)
-{
-#ifdef MOZ_WIDGET_ANDROID
-  AndroidBridge::Bridge()->SetPageRect(aCssPageRect);
-#endif
-}
-
-void
-CompositorParent::SyncViewportInfo(const nsIntRect& aDisplayPort,
-                                   float aDisplayResolution, bool aLayersUpdated,
-                                   nsIntPoint& aScrollOffset, float& aScaleX, float& aScaleY,
-                                   gfx::Margin& aFixedLayerMargins, float& aOffsetX,
-                                   float& aOffsetY)
-{
-#ifdef MOZ_WIDGET_ANDROID
-  AndroidBridge::Bridge()->SyncViewportInfo(aDisplayPort, aDisplayResolution, aLayersUpdated,
-                                            aScrollOffset, aScaleX, aScaleY, aFixedLayerMargins,
-                                            aOffsetX, aOffsetY);
-#endif
-}
-
 PLayerTransactionParent*
 CompositorParent::AllocPLayerTransaction(const LayersBackend& aBackendHint,
                                          const uint64_t& aId,
                                          TextureFactoryIdentifier* aTextureFactoryIdentifier)
 {
   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.
+  // nullptr before returning from this method, to avoid accessing it elsewhere.
   nsIntRect rect;
   mWidget->GetClientBounds(rect);
 
   if (aBackendHint == mozilla::layers::LAYERS_OPENGL) {
     mLayerManager =
       new LayerManagerComposite(new CompositorOGL(mWidget,
                                                   mEGLSurfaceSize.width,
                                                   mEGLSurfaceSize.height,
                                                   mRenderToEGLSurface));
     mWidget = nullptr;
     mLayerManager->SetCompositorID(mCompositorID);
 
     if (!mLayerManager->Initialize()) {
       NS_ERROR("Failed to init Compositor");
-      return NULL;
+      return nullptr;
     }
 
+    mCompositionManager = new AsyncCompositionManager(mLayerManager);
+
     *aTextureFactoryIdentifier = mLayerManager->GetTextureFactoryIdentifier();
     return new LayerTransactionParent(mLayerManager, this, 0);
-  // Basic layers compositor not yet implemented
-  /*} else if (aBackendHint == mozilla::layers::LAYERS_BASIC) {
-    nsRefPtr<LayerManager> layerManager = new BasicShadowLayerManager(mWidget);
-    mWidget = NULL;
-    mLayerManager = layerManager;
-    LayerManagerComposite* slm = layerManager->AsLayerManagerComposite();
-    if (!slm) {
-      return NULL;
-    }
-    *aTextureFactoryIdentifier = layerManager->GetTextureFactoryIdentifier();
-    return new LayerTransactionParent(slm, this, 0); */
   } else {
     NS_ERROR("Unsupported backend selected for Async Compositor");
-    return NULL;
+    return nullptr;
   }
 }
 
 bool
 CompositorParent::DeallocPLayerTransaction(PLayerTransactionParent* actor)
 {
   delete actor;
   return true;
@@ -1211,17 +631,17 @@ CompositorParent* CompositorParent::Remo
   if (it == sCompositorMap->end()) {
     return nullptr;
   }
   CompositorParent *retval = it->second;
   sCompositorMap->erase(it);
   return retval;
 }
 
-typedef map<uint64_t, LayerTreeState> LayerTreeMap;
+typedef map<uint64_t, CompositorParent::LayerTreeState> LayerTreeMap;
 static LayerTreeMap sIndirectLayerTrees;
 
 /*static*/ uint64_t
 CompositorParent::AllocateLayerTreeId()
 {
   MOZ_ASSERT(CompositorLoop());
   MOZ_ASSERT(NS_IsMainThread());
   static uint64_t ids;
@@ -1355,18 +775,18 @@ UpdateIndirectTree(uint64_t aId, Layer* 
   sIndirectLayerTrees[aId].mTargetConfig = aTargetConfig;
   if (ContainerLayer* root = aRoot->AsContainerLayer()) {
     if (AsyncPanZoomController* apzc = sIndirectLayerTrees[aId].mController) {
       apzc->NotifyLayersUpdated(root->GetFrameMetrics(), isFirstPaint);
     }
   }
 }
 
-static const LayerTreeState*
-GetIndirectShadowTree(uint64_t aId)
+/* static */ const CompositorParent::LayerTreeState*
+CompositorParent::GetIndirectShadowTree(uint64_t aId)
 {
   LayerTreeMap::const_iterator cit = sIndirectLayerTrees.find(aId);
   if (sIndirectLayerTrees.end() == cit) {
     return nullptr;
   }
   return &cit->second;
 }
 
--- a/gfx/layers/ipc/CompositorParent.h
+++ b/gfx/layers/ipc/CompositorParent.h
@@ -16,50 +16,32 @@
 //#define COMPOSITOR_PERFORMANCE_WARNING
 
 #include "mozilla/layers/PCompositorParent.h"
 #include "mozilla/layers/PLayerTransactionParent.h"
 #include "base/thread.h"
 #include "mozilla/Monitor.h"
 #include "mozilla/TimeStamp.h"
 #include "ShadowLayersManager.h"
-#include "mozilla/layers/LayerManagerComposite.h"
+
 class nsIWidget;
 
 namespace base {
 class Thread;
 }
 
 namespace mozilla {
 namespace layers {
 
 class AsyncPanZoomController;
 class Layer;
-class LayerManager;
+class LayerManagerComposite;
+class AsyncCompositionManager;
 struct TextureFactoryIdentifier;
 
-// Represents (affine) transforms that are calculated from a content view.
-struct ViewTransform {
-  ViewTransform(gfxPoint aTranslation = gfxPoint(),
-                gfxSize aScale = gfxSize(1, 1))
-    : mTranslation(aTranslation)
-    , mScale(aScale)
-  {}
-
-  operator gfx3DMatrix() const
-  {
-    return
-      gfx3DMatrix::ScalingMatrix(mScale.width, mScale.height, 1) *
-      gfx3DMatrix::Translation(mTranslation.x, mTranslation.y, 0);
-  }
-
-  gfxPoint mTranslation;
-  gfxSize mScale;
-};
-
 class CompositorParent : public PCompositorParent,
                          public ShadowLayersManager
 {
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CompositorParent)
 
 public:
   CompositorParent(nsIWidget* aWidget,
                    bool aRenderToEGLSurface = false,
@@ -81,22 +63,23 @@ public:
                                    bool isFirstPaint) MOZ_OVERRIDE;
   /**
    * This forces the is-first-paint flag to true. This is intended to
    * be called by the widget code when it loses its viewport information
    * (or for whatever reason wants to refresh the viewport information).
    * The information refresh happens because the compositor will call
    * SetFirstPaintViewport on the next frame of composition.
    */
-  void ForceIsFirstPaint() { mIsFirstPaint = true; }
+  void ForceIsFirstPaint();
   void Destroy();
 
   LayerManagerComposite* GetLayerManager() { return mLayerManager; }
 
   void SetTransformation(float aScale, nsIntPoint aScrollOffset);
+
   void AsyncRender();
 
   // Can be called from any thread
   void ScheduleRenderOnCompositorThread();
   void SchedulePauseOnCompositorThread();
   /**
    * Returns true if a surface was obtained and the resume succeeded; false
    * otherwise.
@@ -162,54 +145,47 @@ public:
    * Setup external message loop and thread ID for Compositor.
    * Should be used when CompositorParent should work in existing thread/MessageLoop,
    * for example moving Compositor into native toolkit main thread will allow to avoid
    * extra synchronization and call ::Composite() right from toolkit::Paint event
    */
   static void StartUpWithExistingThread(MessageLoop* aMsgLoop,
                                         PlatformThreadId aThreadID);
 
+  struct LayerTreeState {
+    nsRefPtr<Layer> mRoot;
+    nsRefPtr<AsyncPanZoomController> mController;
+    TargetConfig mTargetConfig;
+  };
+
+  /**
+   * Lookup the indirect shadow tree for |aId| and return it if it
+   * exists.  Otherwise null is returned.  This must only be called on
+   * the compositor thread.
+   */
+  static const LayerTreeState* GetIndirectShadowTree(uint64_t aId);
+
 protected:
   virtual PLayerTransactionParent*
     AllocPLayerTransaction(const LayersBackend& aBackendHint,
                            const uint64_t& aId,
                            TextureFactoryIdentifier* aTextureFactoryIdentifier);
   virtual bool DeallocPLayerTransaction(PLayerTransactionParent* aLayers);
   virtual void ScheduleTask(CancelableTask*, int);
   virtual void Composite();
   virtual void ComposeToTarget(gfxContext* aTarget);
-  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,
-                                gfx::Margin& aFixedLayerMargins, float& aOffsetX, float& aOffsetY);
-  virtual void SyncFrameMetrics(Layer* aLayer, const ViewTransform& aTreeTransform,
-                                const gfxPoint& aScrollOffset, gfx::Margin& aFixedLayerMargins,
-                                float& aOffsetX, float& aOffsetY,
-                                bool aIsFirstPaint, bool aLayersUpdated) {
-  }
 
   void SetEGLSurfaceSize(int width, int height);
 
 private:
   void PauseComposition();
   void ResumeComposition();
   void ResumeCompositionAndResize(int width, int height);
   void ForceComposition();
 
-  // Sample transforms for layer trees.  Return true to request
-  // another animation frame.
-  bool TransformShadowTree(TimeStamp aCurrentFrame);
-  void TransformScrollableLayer(Layer* aLayer, const gfx3DMatrix& aRootTransform);
-  // Return true if an AsyncPanZoomController content transform was
-  // applied for |aLayer|.  *aWantNextFrame is set to true if the
-  // controller wants another animation frame.
-  bool ApplyAsyncContentTransformToTree(TimeStamp aCurrentFrame, Layer* aLayer,
-                                        bool* aWantNextFrame);
-
   inline PlatformThreadId CompositorThreadID();
 
   /**
    * Creates a global map referencing each compositor by ID.
    *
    * This map is used by the ImageBridge protocol to trigger
    * compositions without having to keep references to the
    * compositor
@@ -247,54 +223,26 @@ private:
   static CompositorParent* RemoveCompositor(uint64_t id);
 
    /**
    * Return true if current state allows compositing, that is
    * finishing a layers transaction.
    */
   bool CanComposite();
 
-  // Platform specific functions
-  /**
-   * Recursively applies the given translation to all top-level fixed position
-   * layers that are descendants of the given layer.
-   * aScaleDiff is considered to be the scale transformation applied when
-   * displaying the layers, and is used to make sure the anchor points of
-   * fixed position layers remain in the same position.
-   */
-  void TransformFixedLayers(Layer* aLayer,
-                            const gfxPoint& aTranslation,
-                            const gfxSize& aScaleDiff,
-                            const gfx::Margin& aFixedLayerMargins);
-
   nsRefPtr<LayerManagerComposite> mLayerManager;
+  RefPtr<AsyncCompositionManager> mCompositionManager;
   nsIWidget* mWidget;
-  TargetConfig mTargetConfig;
   CancelableTask *mCurrentCompositeTask;
   TimeStamp mLastCompose;
 #ifdef COMPOSITOR_PERFORMANCE_WARNING
   TimeStamp mExpectedComposeTime;
 #endif
 
   bool mPaused;
-  float mXScale;
-  float mYScale;
-  nsIntPoint mScrollOffset;
-  nsIntRect mContentRect;
-
-  // When this flag is set, the next composition will be the first for a
-  // particular document (i.e. the document displayed on the screen will change).
-  // This happens when loading a new page or switching tabs. We notify the
-  // front-end (e.g. Java on Android) about this so that it take the new page
-  // size and zoom into account when providing us with the next view transform.
-  bool mIsFirstPaint;
-
-  // This flag is set during a layers update, so that the first composition
-  // after a layers update has it set. It is cleared after that first composition.
-  bool mLayersUpdated;
 
   bool mRenderToEGLSurface;
   nsIntSize mEGLSurfaceSize;
 
   mozilla::Monitor mPauseCompositionMonitor;
   mozilla::Monitor mResumeCompositionMonitor;
 
   uint64_t mCompositorID;
--- a/gfx/layers/ipc/ImageBridgeChild.cpp
+++ b/gfx/layers/ipc/ImageBridgeChild.cpp
@@ -12,17 +12,17 @@
 #include "mozilla/Monitor.h"
 #include "mozilla/ReentrantMonitor.h"
 #include "mozilla/layers/CompositableClient.h"
 #include "nsXULAppAPI.h"
 #include "mozilla/layers/TextureClient.h"
 #include "mozilla/layers/ImageClient.h"
 #include "mozilla/layers/LayersTypes.h"
 #include "ShadowLayers.h"
-
+ 
 using namespace base;
 using namespace mozilla::ipc;
 
 namespace mozilla {
 namespace layers {
 
 typedef std::vector<CompositableOperation> OpVector;
 
--- a/gfx/layers/ipc/ImageBridgeParent.cpp
+++ b/gfx/layers/ipc/ImageBridgeParent.cpp
@@ -5,16 +5,17 @@
 
 #include "base/thread.h"
 
 #include "mozilla/layers/CompositorParent.h"
 #include "mozilla/layers/ImageBridgeParent.h"
 #include "CompositableHost.h"
 #include "nsTArray.h"
 #include "nsXULAppAPI.h"
+#include "mozilla/layers/LayerManagerComposite.h"
 
 using namespace base;
 using namespace mozilla::ipc;
 
 namespace mozilla {
 namespace layers {
 
 
--- a/gfx/layers/moz.build
+++ b/gfx/layers/moz.build
@@ -53,16 +53,17 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'wind
             'ShadowLayerUtilsD3D10.h',
         ]
 
 EXPORTS.gfxipc += [
     'ShadowLayerUtils.h',
 ]
 
 EXPORTS.mozilla.layers += [
+    'AsyncCompositionManager.h',
     'AsyncPanZoomController.h',
     'Axis.h',
     'CanvasClient.h',
     'CanvasLayerComposite.h',
     'ColorLayerComposite.h',
     'CompositableClient.h',
     'CompositableTransactionParent.h',
     'Compositor.h',
--- a/layout/ipc/RenderFrameParent.cpp
+++ b/layout/ipc/RenderFrameParent.cpp
@@ -19,16 +19,17 @@
 #include "mozilla/layers/CompositorParent.h"
 #include "mozilla/layers/LayerTransactionParent.h"
 #include "nsContentUtils.h"
 #include "nsFrameLoader.h"
 #include "nsIObserver.h"
 #include "nsSubDocumentFrame.h"
 #include "nsViewportFrame.h"
 #include "RenderFrameParent.h"
+#include "mozilla/layers/LayerManagerComposite.h"
 
 typedef nsContentView::ViewConfig ViewConfig;
 using namespace mozilla::dom;
 using namespace mozilla::layers;
 
 namespace mozilla {
 namespace layout {
 
--- a/widget/android/nsWindow.cpp
+++ b/widget/android/nsWindow.cpp
@@ -35,16 +35,17 @@ using mozilla::unused;
 
 #include "gfxImageSurface.h"
 #include "gfxContext.h"
 
 #include "Layers.h"
 #include "BasicLayers.h"
 #include "LayerManagerOGL.h"
 #include "mozilla/layers/LayerManagerComposite.h"
+#include "mozilla/layers/AsyncCompositionManager.h"
 #include "GLContext.h"
 #include "GLContextProvider.h"
 
 #include "nsTArray.h"
 
 #include "AndroidBridge.h"
 #include "android_npapi.h"