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 id24605
push userkwierso@gmail.com
push dateMon, 29 Apr 2013 21:47:00 +0000
treeherdermozilla-central@dd0c611a0a27 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersBenWa
bugs861727
milestone23.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 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"