Bug 711168 - Implement the compositor protocol for OMTC. r=cjones
authorBenoit Girard <b56girard@gmail.com>, Ali Juma <ajuma@mozilla.com>
Thu, 19 Jan 2012 09:45:37 -0500
changeset 84910 5bd7228ca8a7f416e1cf38adbde530dcdf741f79
parent 84896 622f1d1e7c52e19686f00ff322e9daaf2479326e
child 84911 173c06d3dd71eaa3d791fd402b862275399bf58a
push id21883
push userbmo@edmorley.co.uk
push dateFri, 20 Jan 2012 01:24:53 +0000
treeherdermozilla-central@5c2bc94d359c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerscjones
bugs711168
milestone12.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 711168 - Implement the compositor protocol for OMTC. r=cjones
gfx/layers/Makefile.in
gfx/layers/ipc/CompositorChild.cpp
gfx/layers/ipc/CompositorChild.h
gfx/layers/ipc/CompositorCocoaWidgetHelper.cpp
gfx/layers/ipc/CompositorCocoaWidgetHelper.h
gfx/layers/ipc/CompositorParent.cpp
gfx/layers/ipc/CompositorParent.h
gfx/layers/ipc/PCompositor.ipdl
gfx/layers/ipc/PLayers.ipdl
gfx/layers/ipc/ShadowLayersManager.h
gfx/layers/ipc/ShadowLayersParent.cpp
gfx/layers/ipc/ShadowLayersParent.h
gfx/layers/ipc/ipdl.mk
layout/ipc/RenderFrameParent.cpp
layout/ipc/RenderFrameParent.h
widget/cocoa/nsChildView.h
widget/cocoa/nsChildView.mm
widget/xpwidgets/nsBaseWidget.cpp
widget/xpwidgets/nsBaseWidget.h
--- a/gfx/layers/Makefile.in
+++ b/gfx/layers/Makefile.in
@@ -126,22 +126,29 @@ CPPSRCS += \
         ThebesLayerD3D10.cpp \
         $(NULL)
 endif
 endif
 
 EXPORTS_NAMESPACES = gfxipc mozilla/layers
 EXPORTS_gfxipc = ShadowLayerUtils.h
 EXPORTS_mozilla/layers =\
+        CompositorCocoaWidgetHelper.h \
+        CompositorChild.h \
+        CompositorParent.h \
         ShadowLayers.h \
         ShadowLayersChild.h \
         ShadowLayersParent.h \
+        ShadowLayersManager.h \
         $(NULL)
 
 CPPSRCS += \
+        CompositorCocoaWidgetHelper.cpp \
+        CompositorChild.cpp \
+        CompositorParent.cpp \
         ShadowLayers.cpp \
         ShadowLayerChild.cpp \
         ShadowLayersChild.cpp \
         ShadowLayerParent.cpp \
         ShadowLayersParent.cpp \
         $(NULL)
 
 ifdef MOZ_X11 #{
new file mode 100644
--- /dev/null
+++ b/gfx/layers/ipc/CompositorChild.cpp
@@ -0,0 +1,93 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim: set sw=2 ts=2 et tw=80 : */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Content App.
+ *
+ * The Initial Developer of the Original Code is
+ *   The Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Benoit Girard <bgirard@mozilla.com>
+ *   Ali Juma <ajuma@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "CompositorChild.h"
+#include "CompositorParent.h"
+#include "LayerManagerOGL.h"
+#include "mozilla/layers/ShadowLayersChild.h"
+
+using mozilla::layers::ShadowLayersChild;
+
+namespace mozilla {
+namespace layers {
+
+CompositorChild::CompositorChild(LayerManager *aLayerManager)
+  : mLayerManager(aLayerManager)
+{
+  MOZ_COUNT_CTOR(CompositorChild);
+}
+
+CompositorChild::~CompositorChild()
+{
+  MOZ_COUNT_DTOR(CompositorChild);
+}
+
+void
+CompositorChild::Destroy()
+{
+  mLayerManager = NULL;
+  size_t numChildren = ManagedPLayersChild().Length();
+  NS_ABORT_IF_FALSE(0 == numChildren || 1 == numChildren,
+                    "compositor must only have 0 or 1 layer forwarder");
+
+  if (numChildren) {
+    ShadowLayersChild* layers =
+      static_cast<ShadowLayersChild*>(ManagedPLayersChild()[0]);
+    layers->Destroy();
+  }
+  SendStop();
+}
+
+PLayersChild*
+CompositorChild::AllocPLayers(const LayersBackend &backend)
+{
+  return new ShadowLayersChild();
+}
+
+bool
+CompositorChild::DeallocPLayers(PLayersChild* actor)
+{
+  delete actor;
+  return true;
+}
+
+} // namespace layers
+} // namespace mozilla
+
new file mode 100644
--- /dev/null
+++ b/gfx/layers/ipc/CompositorChild.h
@@ -0,0 +1,73 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim: set sw=4 ts=8 et tw=80 : */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Content App.
+ *
+ * The Initial Developer of the Original Code is
+ *   The Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Benoit Girard <bgirard@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef mozilla_layers_CompositorChild_h
+#define mozilla_layers_CompositorChild_h
+
+#include "mozilla/layers/PCompositorChild.h"
+
+namespace mozilla {
+namespace layers {
+
+class LayerManager;
+class CompositorParent;
+
+class CompositorChild : public PCompositorChild
+{
+  NS_INLINE_DECL_REFCOUNTING(CompositorChild)
+public:
+  CompositorChild(LayerManager *aLayerManager);
+  virtual ~CompositorChild();
+
+  void Destroy();
+
+protected:
+  virtual PLayersChild* AllocPLayers(const LayersBackend &aBackend);
+  virtual bool DeallocPLayers(PLayersChild *aChild);
+
+private:
+  nsRefPtr<LayerManager> mLayerManager;
+
+  DISALLOW_EVIL_CONSTRUCTORS(CompositorChild);
+};
+
+} // layers
+} // mozilla
+
+#endif // mozilla_layers_CompositorChild_h
new file mode 100644
--- /dev/null
+++ b/gfx/layers/ipc/CompositorCocoaWidgetHelper.cpp
@@ -0,0 +1,58 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set sw=2 ts=2 et tw=80 : */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Content App.
+ *
+ * The Initial Developer of the Original Code is
+ *   The Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Benoit Girard <bgirard@mozilla.com>
+ *   Ali Juma <ajuma@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "CompositorParent.h"
+#include "CompositorCocoaWidgetHelper.h"
+#include "nsDebug.h"
+
+namespace mozilla {
+namespace layers {
+namespace compositor {
+
+LayerManager*
+GetLayerManager(CompositorParent* aParent)
+{
+  return aParent->GetLayerManager();
+}
+
+
+}
+}
+}
new file mode 100644
--- /dev/null
+++ b/gfx/layers/ipc/CompositorCocoaWidgetHelper.h
@@ -0,0 +1,63 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim: set sw=4 ts=8 et tw=80 : */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Content App.
+ *
+ * The Initial Developer of the Original Code is
+ *   The Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Benoit Girard <bgirard@mozilla.com>
+ *   Ali Juma <ajuma@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef mozilla_layers_CompositorCocoaWidgetHelper_h
+#define mozilla_layers_CompositorCocoaWidgetHelper_h
+
+// Note we can't include IPDL-generated headers here, since this file is being
+// used as a workaround for Bug 719036.
+
+namespace mozilla {
+namespace layers {
+
+class CompositorParent;
+class LayerManager;
+
+namespace compositor {
+
+// Needed when we cannot directly include CompositorParent.h since it includes
+// an IPDL-generated header (e.g. in widget/cocoa/nsChildView.mm; see Bug 719036).
+LayerManager* GetLayerManager(CompositorParent* aParent);
+
+}
+}
+}
+#endif // mozilla_layers_CompositorCocoaWidgetHelper_h
+
new file mode 100644
--- /dev/null
+++ b/gfx/layers/ipc/CompositorParent.cpp
@@ -0,0 +1,159 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim: set sw=2 ts=2 et tw=80 : */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Content App.
+ *
+ * The Initial Developer of the Original Code is
+ *   The Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Benoit Girard <bgirard@mozilla.com>
+ *   Ali Juma <ajuma@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "CompositorParent.h"
+#include "ShadowLayersParent.h"
+#include "LayerManagerOGL.h"
+#include "nsIWidget.h"
+
+namespace mozilla {
+namespace layers {
+
+CompositorParent::CompositorParent(nsIWidget* aWidget)
+  : mStopped(false), mWidget(aWidget)
+{
+  MOZ_COUNT_CTOR(CompositorParent);
+}
+
+CompositorParent::~CompositorParent()
+{
+  MOZ_COUNT_DTOR(CompositorParent);
+}
+
+void
+CompositorParent::Destroy()
+{
+  NS_ABORT_IF_FALSE(ManagedPLayersParent().Length() == 0,
+                    "CompositorParent destroyed before managed PLayersParent");
+
+  // Ensure that the layer manager is destroyed on the compositor thread.
+  mLayerManager = NULL;
+}
+
+bool
+CompositorParent::RecvStop()
+{
+  mStopped = true;
+  Destroy();
+  return true;
+}
+
+void
+CompositorParent::ScheduleComposition()
+{
+  CancelableTask *composeTask = NewRunnableMethod(this, &CompositorParent::Composite);
+  MessageLoop::current()->PostTask(FROM_HERE, composeTask);
+}
+
+void
+CompositorParent::Composite()
+{
+  if (mStopped || !mLayerManager) {
+    return;
+  }
+
+  mLayerManager->EndEmptyTransaction();
+}
+
+// Go down shadow layer tree, setting properties to match their non-shadow
+// counterparts.
+static void
+SetShadowProperties(Layer* aLayer)
+{
+  // FIXME: Bug 717688 -- Do these updates in ShadowLayersParent::RecvUpdate.
+  ShadowLayer* shadow = aLayer->AsShadowLayer();
+  shadow->SetShadowTransform(aLayer->GetTransform());
+  shadow->SetShadowVisibleRegion(aLayer->GetVisibleRegion());
+  shadow->SetShadowClipRect(aLayer->GetClipRect());
+
+  for (Layer* child = aLayer->GetFirstChild();
+      child; child = child->GetNextSibling()) {
+    SetShadowProperties(child);
+  }
+}
+
+void
+CompositorParent::ShadowLayersUpdated()
+{
+  const nsTArray<PLayersParent*>& shadowParents = ManagedPLayersParent();
+  NS_ABORT_IF_FALSE(shadowParents.Length() <= 1,
+                    "can only support at most 1 ShadowLayersParent");
+  if (shadowParents.Length()) {
+    Layer* root = static_cast<ShadowLayersParent*>(shadowParents[0])->GetRoot();
+    mLayerManager->SetRoot(root);
+    SetShadowProperties(root);
+  }
+  ScheduleComposition();
+}
+
+PLayersParent*
+CompositorParent::AllocPLayers(const LayersBackend &backendType)
+{
+  if (backendType == LayerManager::LAYERS_OPENGL) {
+    nsRefPtr<LayerManagerOGL> layerManager = new LayerManagerOGL(mWidget);
+    mWidget = NULL;
+    mLayerManager = layerManager;
+
+    if (!layerManager->Initialize()) {
+      NS_ERROR("Failed to init OGL Layers");
+      return NULL;
+    }
+
+    ShadowLayerManager* slm = layerManager->AsShadowManager();
+    if (!slm) {
+      return NULL;
+    }
+    return new ShadowLayersParent(slm, this);
+  } else {
+    NS_ERROR("Unsupported backend selected for Async Compositor");
+    return NULL;
+  }
+}
+
+bool
+CompositorParent::DeallocPLayers(PLayersParent* actor)
+{
+  delete actor;
+  return true;
+}
+
+} // namespace layers
+} // namespace mozilla
+
new file mode 100644
--- /dev/null
+++ b/gfx/layers/ipc/CompositorParent.h
@@ -0,0 +1,88 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim: set sw=4 ts=8 et tw=80 : */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Content App.
+ *
+ * The Initial Developer of the Original Code is
+ *   The Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Benoit Girard <bgirard@mozilla.com>
+ *   Ali Juma <ajuma@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef mozilla_layers_CompositorParent_h
+#define mozilla_layers_CompositorParent_h
+
+#include "mozilla/layers/PCompositorParent.h"
+#include "mozilla/layers/PLayersParent.h"
+#include "ShadowLayersManager.h"
+
+class nsIWidget;
+
+namespace mozilla {
+namespace layers {
+
+class LayerManager;
+
+class CompositorParent : public PCompositorParent,
+                         public ShadowLayersManager
+{
+  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CompositorParent)
+public:
+  CompositorParent(nsIWidget* aWidget);
+  virtual ~CompositorParent();
+
+  virtual bool RecvStop() MOZ_OVERRIDE;
+
+  virtual void ShadowLayersUpdated() MOZ_OVERRIDE;
+  void Destroy();
+
+  LayerManager* GetLayerManager() { return mLayerManager; }
+
+protected:
+  virtual PLayersParent* AllocPLayers(const LayersBackend &backendType);
+  virtual bool DeallocPLayers(PLayersParent* aLayers);
+
+private:
+  void ScheduleComposition();
+  void Composite();
+
+  nsRefPtr<LayerManager> mLayerManager;
+  bool mStopped;
+  nsIWidget* mWidget;
+
+  DISALLOW_EVIL_CONSTRUCTORS(CompositorParent);
+};
+
+} // layers
+} // mozilla
+
+#endif // mozilla_layers_CompositorParent_h
new file mode 100644
--- /dev/null
+++ b/gfx/layers/ipc/PCompositor.ipdl
@@ -0,0 +1,71 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: sw=2 ts=8 et :
+ */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at:
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Code.
+ *
+ * The Initial Developer of the Original Code is
+ *   The Mozilla Foundation
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Benoit Girard <bgirard@mozilla.com>
+ *   Ali Juma <ajuma@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+include protocol PLayers;
+
+using mozilla::LayersBackend;
+using mozilla::null_t;
+
+namespace mozilla {
+namespace layers {
+
+/**
+ * The PCompositor protocol is used to manage communication between
+ * the main thread and the compositor thread context. It's primary
+ * purpose is to manage the PLayers sub protocol.
+ */
+// This should really be 'sync', but we're using 'rpc' as a workaround
+// for Bug 716631.
+rpc protocol PCompositor
+{
+  // A Compositor manages a single Layer Manager (PLayers)
+  manages PLayers;
+
+parent:  
+
+  // Clean up in preparation for destruction.
+  sync Stop();
+
+  sync PLayers(LayersBackend backend);
+};
+
+} // layers
+} // mozilla
--- a/gfx/layers/ipc/PLayers.ipdl
+++ b/gfx/layers/ipc/PLayers.ipdl
@@ -33,17 +33,17 @@
  * use your version of this file under the terms of the MPL, indicate your
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
-//include protocol PCompositor;
+include protocol PCompositor;
 include protocol PLayer;
 include protocol PRenderFrame;
 
 include "gfxipc/ShadowLayerUtils.h";
 
 using gfx3DMatrix;
 using gfxRGBA;
 using nsIntPoint;
@@ -221,17 +221,17 @@ struct OpThebesBufferSwap {
 union EditReply {
   OpBufferSwap;
   OpThebesBufferSwap;
   OpImageSwap;
 };
 
 
 sync protocol PLayers {
-  manager PRenderFrame /*or PCompositor or PMedia or PPlugin*/;
+  manager PRenderFrame or PCompositor;
   manages PLayer;
 
 parent:
   async PLayer();
 
   sync Update(Edit[] cset)
     returns (EditReply[] reply);
 
new file mode 100644
--- /dev/null
+++ b/gfx/layers/ipc/ShadowLayersManager.h
@@ -0,0 +1,63 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim: set sw=4 ts=8 et tw=80 : */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Content App.
+ *
+ * The Initial Developer of the Original Code is
+ *   The Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Ali Juma <ajuma@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef mozilla_layers_ShadowLayersManager_h
+#define mozilla_layers_ShadowLayersManager_h
+
+namespace mozilla {
+
+namespace layout {
+class RenderFrameParent;
+}
+
+namespace layers {
+
+class CompositorParent;
+
+class ShadowLayersManager
+{
+
+public:
+  virtual void ShadowLayersUpdated() = 0;
+};
+
+} // layers
+} // mozilla
+
+#endif // mozilla_layers_ShadowLayersManager_h
--- a/gfx/layers/ipc/ShadowLayersParent.cpp
+++ b/gfx/layers/ipc/ShadowLayersParent.cpp
@@ -42,16 +42,17 @@
 
 #include "ShadowLayersParent.h"
 #include "ShadowLayerParent.h"
 #include "ShadowLayers.h"
 
 #include "mozilla/unused.h"
 
 #include "mozilla/layout/RenderFrameParent.h"
+#include "CompositorParent.h"
 
 #include "gfxSharedImageSurface.h"
 
 #include "ImageLayers.h"
 
 typedef std::vector<mozilla::layers::EditReply> EditReplyVector;
 
 using mozilla::layout::RenderFrameParent;
@@ -116,21 +117,21 @@ ShadowContainer(const OpRemoveChild& op)
 static ShadowLayerParent*
 ShadowChild(const OpRemoveChild& op)
 {
   return cast(op.childLayerParent());
 }
 
 //--------------------------------------------------
 // ShadowLayersParent
-ShadowLayersParent::ShadowLayersParent(ShadowLayerManager* aManager)
-  : mDestroyed(false)
+ShadowLayersParent::ShadowLayersParent(ShadowLayerManager* aManager,
+                                       ShadowLayersManager* aLayersManager)
+  : mLayerManager(aManager), mShadowLayersManager(aLayersManager), mDestroyed(false)
 {
   MOZ_COUNT_CTOR(ShadowLayersParent);
-  mLayerManager = aManager;
 }
 
 ShadowLayersParent::~ShadowLayersParent()
 {
   MOZ_COUNT_DTOR(ShadowLayersParent);
 }
 
 void
@@ -377,17 +378,17 @@ ShadowLayersParent::RecvUpdate(const Inf
     reply->AppendElements(&replyv.front(), replyv.size());
   }
 
   // Ensure that any pending operations involving back and front
   // buffers have completed, so that neither process stomps on the
   // other's buffer contents.
   ShadowLayerManager::PlatformSyncBeforeReplyUpdate();
 
-  Frame()->ShadowLayersUpdated();
+  mShadowLayersManager->ShadowLayersUpdated();
 
   return true;
 }
 
 PLayerParent*
 ShadowLayersParent::AllocPLayer()
 {
   return new ShadowLayerParent();
@@ -395,22 +396,16 @@ ShadowLayersParent::AllocPLayer()
 
 bool
 ShadowLayersParent::DeallocPLayer(PLayerParent* actor)
 {
   delete actor;
   return true;
 }
 
-RenderFrameParent*
-ShadowLayersParent::Frame()
-{
-  return static_cast<RenderFrameParent*>(Manager());
-}
-
 void
 ShadowLayersParent::DestroySharedSurface(gfxSharedImageSurface* aSurface)
 {
   layer_manager()->DestroySharedSurface(aSurface, this);
 }
 
 void
 ShadowLayersParent::DestroySharedSurface(SurfaceDescriptor* aSurface)
--- a/gfx/layers/ipc/ShadowLayersParent.h
+++ b/gfx/layers/ipc/ShadowLayersParent.h
@@ -38,16 +38,17 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef mozilla_layers_ShadowLayersParent_h
 #define mozilla_layers_ShadowLayersParent_h
 
 #include "mozilla/layers/PLayersParent.h"
 #include "ShadowLayers.h"
+#include "ShadowLayersManager.h"
 
 namespace mozilla {
 
 namespace layout {
 class RenderFrameParent;
 }
 
 namespace layers {
@@ -58,17 +59,17 @@ class ShadowLayerManager;
 class ShadowLayersParent : public PLayersParent,
                            public ISurfaceDeAllocator
 {
   typedef mozilla::layout::RenderFrameParent RenderFrameParent;
   typedef InfallibleTArray<Edit> EditArray;
   typedef InfallibleTArray<EditReply> EditReplyArray;
 
 public:
-  ShadowLayersParent(ShadowLayerManager* aManager);
+  ShadowLayersParent(ShadowLayerManager* aManager, ShadowLayersManager* aLayersManager);
   ~ShadowLayersParent();
 
   void Destroy();
 
   ShadowLayerManager* layer_manager() const { return mLayerManager; }
 
   ContainerLayer* GetRoot() const { return mRoot; }
 
@@ -78,19 +79,18 @@ public:
 protected:
   NS_OVERRIDE virtual bool RecvUpdate(const EditArray& cset,
                                       EditReplyArray* reply);
 
   NS_OVERRIDE virtual PLayerParent* AllocPLayer();
   NS_OVERRIDE virtual bool DeallocPLayer(PLayerParent* actor);
 
 private:
-  RenderFrameParent* Frame();
-
   nsRefPtr<ShadowLayerManager> mLayerManager;
+  ShadowLayersManager* mShadowLayersManager;
   // Hold the root because it might be grafted under various
   // containers in the "real" layer tree
   nsRefPtr<ContainerLayer> mRoot;
   // When the widget/frame/browser stuff in this process begins its
   // destruction process, we need to Disconnect() all the currently
   // live shadow layers, because some of them might be orphaned from
   // the layer tree.  This happens in Destroy() above.  After we
   // Destroy() ourself, there's a window in which that information
--- a/gfx/layers/ipc/ipdl.mk
+++ b/gfx/layers/ipc/ipdl.mk
@@ -1,4 +1,5 @@
 IPDLSRCS = \
+  PCompositor.ipdl \
   PLayer.ipdl \
   PLayers.ipdl \
   $(NULL)
--- a/layout/ipc/RenderFrameParent.cpp
+++ b/layout/ipc/RenderFrameParent.cpp
@@ -643,17 +643,17 @@ RenderFrameParent::AllocPLayers(LayerMan
   }
   LayerManager* lm = GetLayerManager();
   ShadowLayerManager* slm = lm->AsShadowManager();
   if (!slm) {
     *aBackendType = LayerManager::LAYERS_NONE;
      return nsnull;
   }
   *aBackendType = lm->GetBackendType();
-  return new ShadowLayersParent(slm);
+  return new ShadowLayersParent(slm, this);
 }
 
 bool
 RenderFrameParent::DeallocPLayers(PLayersParent* aLayers)
 {
   delete aLayers;
   return true;
 }
--- a/layout/ipc/RenderFrameParent.h
+++ b/layout/ipc/RenderFrameParent.h
@@ -37,16 +37,17 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef mozilla_layout_RenderFrameParent_h
 #define mozilla_layout_RenderFrameParent_h
 
 #include "mozilla/layout/PRenderFrameParent.h"
+#include "mozilla/layers/ShadowLayersManager.h"
 
 #include <map>
 #include "nsDisplayList.h"
 #include "Layers.h"
 
 class nsContentView;
 class nsFrameLoader;
 class nsSubDocumentFrame;
@@ -54,17 +55,18 @@ class nsSubDocumentFrame;
 namespace mozilla {
 
 namespace layers {
 class ShadowLayersParent;
 }
 
 namespace layout {
 
-class RenderFrameParent : public PRenderFrameParent
+class RenderFrameParent : public PRenderFrameParent,
+                          public mozilla::layers::ShadowLayersManager
 {
   typedef mozilla::layers::FrameMetrics FrameMetrics;
   typedef mozilla::layers::ContainerLayer ContainerLayer;
   typedef mozilla::layers::Layer Layer;
   typedef mozilla::layers::LayerManager LayerManager;
   typedef mozilla::layers::ShadowLayersParent ShadowLayersParent;
   typedef FrameMetrics::ViewID ViewID;
 
@@ -79,17 +81,17 @@ public:
   /**
    * Helper function for getting a non-owning reference to a scrollable.
    * @param aId The ID of the frame.
    */
   nsContentView* GetContentView(ViewID aId = FrameMetrics::ROOT_SCROLL_ID);
 
   void ContentViewScaleChanged(nsContentView* aView);
 
-  void ShadowLayersUpdated();
+  virtual void ShadowLayersUpdated() MOZ_OVERRIDE;
 
   NS_IMETHOD BuildDisplayList(nsDisplayListBuilder* aBuilder,
                               nsSubDocumentFrame* aFrame,
                               const nsRect& aDirtyRect,
                               const nsDisplayListSet& aLists);
 
   already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
                                      nsIFrame* aFrame,
--- a/widget/cocoa/nsChildView.h
+++ b/widget/cocoa/nsChildView.h
@@ -114,16 +114,20 @@ class gfxASurface;
 class nsChildView;
 class nsCocoaWindow;
 union nsPluginPort;
 
 namespace mozilla {
 namespace gl {
 class TextureImage;
 }
+
+namespace layers {
+class LayerManagerOGL;
+}
 }
 
 #ifndef NP_NO_CARBON
 enum {
   // Currently focused ChildView (while this TSM document is active).
   // Transient (only set while TSMProcessRawKeyEvent() is processing a key
   // event), and the ChildView will be retained and released around the call
   // to TSMProcessRawKeyEvent() -- so it can be weak.
@@ -290,16 +294,19 @@ typedef NSInteger NSEventGestureAxis;
   float mCumulativeRotation;
 
   BOOL mDidForceRefreshOpenGL;
 
   // Support for fluid swipe tracking.
 #ifdef __LP64__
   BOOL *mSwipeAnimationCancelled;
 #endif
+
+  // Whether this uses off-main-thread compositing.
+  BOOL mUsingOMTCompositor;
 }
 
 // class initialization
 + (void)initialize;
 
 // these are sent to the first responder when the window key status changes
 - (void)viewsWindowDidBecomeKey;
 - (void)viewsWindowDidResignKey;
@@ -322,16 +329,18 @@ typedef NSInteger NSEventGestureAxis;
 - (void) _surfaceNeedsUpdate:(NSNotification*)notification;
 
 - (BOOL)isPluginView;
 
 // Are we processing an NSLeftMouseDown event that will fail to click through?
 // If so, we shouldn't focus or unfocus a plugin.
 - (BOOL)isInFailingLeftClickThrough;
 
+- (void)setGLContext:(NSOpenGLContext *)aGLContext;
+
 // Simple gestures support
 //
 // XXX - The swipeWithEvent, beginGestureWithEvent, magnifyWithEvent,
 // rotateWithEvent, and endGestureWithEvent methods are part of a
 // PRIVATE interface exported by nsResponder and reverse-engineering
 // was necessary to obtain the methods' prototypes. Thus, Apple may
 // change the interface in the future without notice.
 //
@@ -343,16 +352,18 @@ typedef NSInteger NSEventGestureAxis;
 - (void)rotateWithEvent:(NSEvent *)anEvent;
 - (void)endGestureWithEvent:(NSEvent *)anEvent;
 
 // Support for fluid swipe tracking.
 #ifdef __LP64__
 - (void)maybeTrackScrollEventAsSwipe:(NSEvent *)anEvent
                       scrollOverflow:(PRInt32)overflow;
 #endif
+
+- (void)setUsingOMTCompositor:(BOOL)aUseOMTC;
 @end
 
 class ChildViewMouseTracker {
 
 public:
 
   static void MouseMoved(NSEvent* aEvent);
   static void MouseScrolled(NSEvent* aEvent);
@@ -428,17 +439,17 @@ public:
   static  bool            ConvertStatus(nsEventStatus aStatus)
                           { return aStatus == nsEventStatus_eConsumeNoDefault; }
   NS_IMETHOD              DispatchEvent(nsGUIEvent* event, nsEventStatus & aStatus);
 
   virtual bool            GetShouldAccelerate();
 
   NS_IMETHOD        SetCursor(nsCursor aCursor);
   NS_IMETHOD        SetCursor(imgIContainer* aCursor, PRUint32 aHotspotX, PRUint32 aHotspotY);
-  
+
   NS_IMETHOD        CaptureRollupEvents(nsIRollupListener * aListener, bool aDoCapture, bool aConsumeRollupEvent);
   NS_IMETHOD        SetTitle(const nsAString& title);
 
   NS_IMETHOD        GetAttention(PRInt32 aCycleCount);
 
   virtual bool HasPendingInputEvent();
 
   NS_IMETHOD        ActivateNativeMenuItemAt(const nsAString& indexString);
@@ -481,16 +492,17 @@ public:
   // Mac specific methods
   
   virtual bool      DispatchWindowEvent(nsGUIEvent& event);
   
 #ifdef ACCESSIBILITY
   already_AddRefed<nsAccessible> GetDocumentAccessible();
 #endif
 
+  virtual void CreateCompositor();
   virtual gfxASurface* GetThebesSurface();
   virtual void DrawOver(LayerManager* aManager, nsIntRect aRect);
 
   virtual void UpdateThemeGeometries(const nsTArray<ThemeGeometry>& aThemeGeometries);
 
   NS_IMETHOD BeginSecureKeyboardInput();
   NS_IMETHOD EndSecureKeyboardInput();
 
--- a/widget/cocoa/nsChildView.mm
+++ b/widget/cocoa/nsChildView.mm
@@ -82,16 +82,17 @@
 #endif
 
 #include "gfxContext.h"
 #include "gfxQuartzSurface.h"
 #include "nsRegion.h"
 #include "Layers.h"
 #include "LayerManagerOGL.h"
 #include "GLContext.h"
+#include "mozilla/layers/CompositorCocoaWidgetHelper.h"
 
 #include "mozilla/Preferences.h"
 
 #include <dlfcn.h>
 
 #include <ApplicationServices/ApplicationServices.h>
 
 #include "sampler.h"
@@ -1767,16 +1768,32 @@ NSView<mozView>* nsChildView::GetEditorV
     if (view)
       editorView = view;
   }
   return editorView;
 }
 
 #pragma mark -
 
+void
+nsChildView::CreateCompositor()
+{
+  nsBaseWidget::CreateCompositor();
+  if (mCompositorChild) {
+    LayerManagerOGL *manager =
+      static_cast<LayerManagerOGL*>(compositor::GetLayerManager(mCompositorParent));
+
+    NSOpenGLContext *glContext =
+      (NSOpenGLContext *) manager->gl()->GetNativeData(GLContext::NativeGLContext);
+
+    [(ChildView *)mView setGLContext:glContext];
+    [(ChildView *)mView setUsingOMTCompositor:true];
+  }
+}
+
 gfxASurface*
 nsChildView::GetThebesSurface()
 {
   if (!mTempThebesSurface) {
     mTempThebesSurface = new gfxQuartzSurface(gfxSize(1, 1), gfxASurface::ImageFormatARGB32);
   }
 
   return mTempThebesSurface;
@@ -2091,16 +2108,26 @@ NSEvent* gLastDragMouseDownEvent = nil;
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
 
   [mGLContext clearDrawable];
   [mGLContext setView:self];
 
   NS_OBJC_END_TRY_ABORT_BLOCK;
 }
 
+- (void)setGLContext:(NSOpenGLContext *)aGLContext
+{
+  NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
+
+  mGLContext = aGLContext;
+  [mGLContext retain];
+
+  NS_OBJC_END_TRY_ABORT_BLOCK;
+}
+
 - (void)dealloc
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
 
   [mGLContext release];
   [mPendingDirtyRects release];
   [mLastMouseDownEvent release];
   [mClickThroughMouseDownEvent release];
@@ -2541,23 +2568,28 @@ NSEvent* gLastDragMouseDownEvent = nil;
     if ([cview isPluginView] && [cview pluginDrawingModel] == NPDrawingModelQuickDraw) {
       NSRect frame = [view frame];
       paintEvent.region.Sub(paintEvent.region,
         nsIntRect(frame.origin.x, frame.origin.y, frame.size.width, frame.size.height));
     }
   }
 #endif
 
-  if (mGeckoChild->GetLayerManager(nsnull)->GetBackendType() == LayerManager::LAYERS_OPENGL) {
-    LayerManagerOGL *manager = static_cast<LayerManagerOGL*>(mGeckoChild->GetLayerManager(nsnull));
-    manager->SetClippingRegion(paintEvent.region); 
+  LayerManager *layerManager = mGeckoChild->GetLayerManager(nsnull);
+  if (layerManager->GetBackendType() == LayerManager::LAYERS_OPENGL) {
+    NSOpenGLContext *glContext;
+
+    LayerManagerOGL *manager = static_cast<LayerManagerOGL*>(layerManager);
+    manager->SetClippingRegion(paintEvent.region);
+    glContext = (NSOpenGLContext *)manager->gl()->GetNativeData(mozilla::gl::GLContext::NativeGLContext);
+
     if (!mGLContext) {
-      mGLContext = (NSOpenGLContext *)manager->gl()->GetNativeData(mozilla::gl::GLContext::NativeGLContext);
-      [mGLContext retain];
+      [self setGLContext:glContext];
     }
+
     mGeckoChild->DispatchWindowEvent(paintEvent);
 
     // Force OpenGL to refresh the very first time we draw. This works around a
     // Mac OS X bug that stops windows updating on OS X when we use OpenGL.
     if (!mDidForceRefreshOpenGL) {
       [self performSelector:@selector(forceRefreshOpenGL) withObject:nil afterDelay:0];
       mDidForceRefreshOpenGL = YES;
     }
@@ -2587,16 +2619,26 @@ NSEvent* gLastDragMouseDownEvent = nil;
   nsAutoRetainCocoaObject kungFuDeathGrip(self);
   bool painted;
   {
     nsBaseWidget::AutoLayerManagerSetup
       setupLayerManager(mGeckoChild, targetContext, BasicLayerManager::BUFFER_NONE);
     painted = mGeckoChild->DispatchWindowEvent(paintEvent);
   }
 
+  // Force OpenGL to refresh the very first time we draw. This works around a
+  // Mac OS X bug that stops windows updating on OS X when we use OpenGL.
+  if (painted && !mDidForceRefreshOpenGL &&
+      layerManager->AsShadowManager() && mUsingOMTCompositor) {
+    if (!mDidForceRefreshOpenGL) {
+      [self performSelector:@selector(forceRefreshOpenGL) withObject:nil afterDelay:0];
+      mDidForceRefreshOpenGL = YES;
+    }
+  }
+
   if (!painted && [self isOpaque]) {
     // Gecko refused to draw, but we've claimed to be opaque, so we have to
     // draw something--fill with white.
     CGContextSetRGBFillColor(aContext, 1, 1, 1, 1);
     CGContextFillRect(aContext, CGRectMake(aRect.origin.x, aRect.origin.y,
                                            aRect.size.width, aRect.size.height));
   }
 
@@ -3124,16 +3166,22 @@ NSEvent* gLastDragMouseDownEvent = nil;
   // We keep a pointer to the __block variable (animationCanceled) so we
   // can cancel our block handler at any time.  Note: We must assign
   // &animationCanceled after our block creation and copy -- its address
   // isn't resolved until then!
   mSwipeAnimationCancelled = &animationCancelled;
 }
 #endif // #ifdef __LP64__
 
+- (void)setUsingOMTCompositor:(BOOL)aUseOMTC
+{
+  mUsingOMTCompositor = aUseOMTC;
+}
+
+
 // Returning NO from this method only disallows ordering on mousedown - in order
 // to prevent it for mouseup too, we need to call [NSApp preventWindowOrdering]
 // when handling the mousedown event.
 - (BOOL)shouldDelayWindowOrderingForEvent:(NSEvent*)aEvent
 {
   // Always using system-provided window ordering for normal windows.
   if (![[self window] isKindOfClass:[PopupWindow class]])
     return NO;
--- a/widget/xpwidgets/nsBaseWidget.cpp
+++ b/widget/xpwidgets/nsBaseWidget.cpp
@@ -33,16 +33,18 @@
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "mozilla/Util.h"
 
+#include "mozilla/layers/CompositorChild.h"
+#include "mozilla/layers/CompositorParent.h"
 #include "nsBaseWidget.h"
 #include "nsDeviceContext.h"
 #include "nsCOMPtr.h"
 #include "nsGfxCIID.h"
 #include "nsWidgetsCID.h"
 #include "nsServiceManagerUtils.h"
 #include "nsIScreenManager.h"
 #include "nsAppDirectoryServiceDefs.h"
@@ -50,31 +52,34 @@
 #include "nsIContent.h"
 #include "nsIServiceManager.h"
 #include "mozilla/Preferences.h"
 #include "BasicLayers.h"
 #include "LayerManagerOGL.h"
 #include "nsIXULRuntime.h"
 #include "nsIGfxInfo.h"
 #include "npapi.h"
+#include "base/thread.h"
 
 #ifdef DEBUG
 #include "nsIObserver.h"
 
 static void debug_RegisterPrefCallbacks();
 
 static bool debug_InSecureKeyboardInputMode = false;
 #endif
 
 #ifdef NOISY_WIDGET_LEAKS
 static PRInt32 gNumWidgets;
 #endif
 
 using namespace mozilla::layers;
 using namespace mozilla;
+using base::Thread;
+using mozilla::ipc::AsyncChannel;
 
 nsIContent* nsBaseWidget::mLastRollup = nsnull;
 
 // nsBaseWidget
 NS_IMPL_ISUPPORTS1(nsBaseWidget, nsIWidget)
 
 
 nsAutoRollup::nsAutoRollup()
@@ -99,16 +104,17 @@ nsAutoRollup::~nsAutoRollup()
 //-------------------------------------------------------------------------
 
 nsBaseWidget::nsBaseWidget()
 : mClientData(nsnull)
 , mViewWrapperPtr(nsnull)
 , mEventCallback(nsnull)
 , mViewCallback(nsnull)
 , mContext(nsnull)
+, mCompositorThread(nsnull)
 , mCursor(eCursor_standard)
 , mWindowType(eWindowType_child)
 , mBorderStyle(eBorderStyle_none)
 , mOnDestroyCalled(false)
 , mUseAcceleratedRendering(false)
 , mTemporarilyUseBasicLayerManager(false)
 , mBounds(0,0,0,0)
 , mOriginalBounds(nsnull)
@@ -137,16 +143,22 @@ nsBaseWidget::~nsBaseWidget()
 {
   if (mLayerManager &&
       mLayerManager->GetBackendType() == LayerManager::LAYERS_BASIC) {
     static_cast<BasicLayerManager*>(mLayerManager.get())->ClearRetainerWidget();
   }
 
   if (mLayerManager) {
     mLayerManager->Destroy();
+    mLayerManager = nsnull;
+  }
+
+  if (mCompositorChild) {
+    mCompositorChild->Destroy();
+    delete mCompositorThread;
   }
 
 #ifdef NOISY_WIDGET_LEAKS
   gNumWidgets--;
   printf("WIDGETS- = %d\n", gNumWidgets);
 #endif
 
   NS_IF_RELEASE(mContext);
@@ -809,36 +821,81 @@ nsBaseWidget::GetShouldAccelerate()
 
   if (accelerateByDefault)
     return true;
 
   /* use the window acceleration flag */
   return mUseAcceleratedRendering;
 }
 
+void nsBaseWidget::CreateCompositor()
+{
+  mCompositorParent = new CompositorParent(this);
+  mCompositorThread = new Thread("CompositorThread");
+  if (mCompositorThread->Start()) {
+    LayerManager* lm = CreateBasicLayerManager();
+    MessageLoop *childMessageLoop = mCompositorThread->message_loop();
+    mCompositorChild = new CompositorChild(lm);
+    AsyncChannel *parentChannel = mCompositorParent->GetIPCChannel();
+    AsyncChannel::Side childSide = mozilla::ipc::AsyncChannel::Child;
+    mCompositorChild->Open(parentChannel, childMessageLoop, childSide);
+    PLayersChild* shadowManager =
+      mCompositorChild->SendPLayersConstructor(LayerManager::LAYERS_OPENGL);
+
+    if (shadowManager) {
+      ShadowLayerForwarder* lf = lm->AsShadowForwarder();
+      if (!lf) {
+        delete lm;
+        mCompositorChild = nsnull;
+      }
+      lf->SetShadowManager(shadowManager);
+      lf->SetParentBackendType(LayerManager::LAYERS_OPENGL);
+
+      mLayerManager = lm;
+    } else {
+      NS_WARNING("fail to construct LayersChild");
+      delete lm;
+      mCompositorChild = nsnull;
+    }
+  }
+}
+
 LayerManager* nsBaseWidget::GetLayerManager(PLayersChild* aShadowManager,
                                             LayersBackend aBackendHint,
                                             LayerManagerPersistence aPersistence,
                                             bool* aAllowRetaining)
 {
   if (!mLayerManager) {
 
     mUseAcceleratedRendering = GetShouldAccelerate();
 
     if (mUseAcceleratedRendering) {
-      nsRefPtr<LayerManagerOGL> layerManager = new LayerManagerOGL(this);
-      /**
-       * XXX - On several OSes initialization is expected to fail for now.
-       * If we'd get a none-basic layer manager they'd crash. This is ok though
-       * since on those platforms it will fail. Anyone implementing new
-       * platforms on LayerManagerOGL should ensure their widget is able to
-       * deal with it though!
-       */
-      if (layerManager->Initialize()) {
-        mLayerManager = layerManager;
+
+      // Try to use an async compositor first, if possible
+      bool useCompositor =
+        Preferences::GetBool("layers.offmainthreadcomposition.enabled", false);
+      if (useCompositor) {
+        // e10s uses the parameter to pass in the shadow manager from the TabChild
+        // so we don't expect to see it there since this doesn't support e10s.
+        NS_ASSERTION(aShadowManager == nsnull, "Async Compositor not supported with e10s");
+        CreateCompositor();
+      }
+
+      if (!mLayerManager) {
+        nsRefPtr<LayerManagerOGL> layerManager = new LayerManagerOGL(this);
+        /**
+         * XXX - On several OSes initialization is expected to fail for now.
+         * If we'd get a non-basic layer manager they'd crash. This is ok though
+         * since on those platforms it will fail. Anyone implementing new
+         * platforms on LayerManagerOGL should ensure their widget is able to
+         * deal with it though!
+         */
+        if (layerManager->Initialize()) {
+          mLayerManager = layerManager;
+        }
       }
     }
     if (!mLayerManager) {
       mBasicLayerManager = mLayerManager = CreateBasicLayerManager();
     }
   }
   if (mTemporarilyUseBasicLayerManager && !mBasicLayerManager) {
     mBasicLayerManager = CreateBasicLayerManager();
--- a/widget/xpwidgets/nsBaseWidget.h
+++ b/widget/xpwidgets/nsBaseWidget.h
@@ -46,31 +46,45 @@
 #include "nsGUIEvent.h"
 #include "nsAutoPtr.h"
 #include "BasicLayers.h"
 
 class nsIContent;
 class nsAutoRollup;
 class gfxContext;
 
+namespace mozilla {
+namespace layers {
+class CompositorChild;
+class CompositorParent;
+}
+}
+
+namespace base {
+class Thread;
+}
+
 /**
  * Common widget implementation used as base class for native
  * or crossplatform implementations of Widgets. 
  * All cross-platform behavior that all widgets need to implement 
  * should be placed in this class. 
  * (Note: widget implementations are not required to use this
  * class, but it gives them a head start.)
  */
 
 class nsBaseWidget : public nsIWidget
 {
   friend class nsAutoRollup;
 
 protected:
   typedef mozilla::layers::BasicLayerManager BasicLayerManager;
+  typedef mozilla::layers::CompositorChild CompositorChild;
+  typedef mozilla::layers::CompositorParent CompositorParent;
+  typedef base::Thread Thread;
 
 public:
   nsBaseWidget();
   virtual ~nsBaseWidget();
   
   NS_DECL_ISUPPORTS
   
   // nsIWidget interface
@@ -112,16 +126,17 @@ public:
   NS_IMETHOD              HideWindowChrome(bool aShouldHide);
   NS_IMETHOD              MakeFullScreen(bool aFullScreen);
   virtual nsDeviceContext* GetDeviceContext();
   virtual LayerManager*   GetLayerManager(PLayersChild* aShadowManager = nsnull,
                                           LayersBackend aBackendHint = LayerManager::LAYERS_NONE,
                                           LayerManagerPersistence aPersistence = LAYER_MANAGER_CURRENT,
                                           bool* aAllowRetaining = nsnull);
 
+  virtual void            CreateCompositor();
   virtual void            DrawOver(LayerManager* aManager, nsIntRect aRect) {}
   virtual void            UpdateThemeGeometries(const nsTArray<ThemeGeometry>& aThemeGeometries) {}
   virtual gfxASurface*    GetThebesSurface();
   NS_IMETHOD              SetModal(bool aModal); 
   NS_IMETHOD              SetWindowClass(const nsAString& xulWinType);
   NS_IMETHOD              MoveClient(PRInt32 aX, PRInt32 aY);
   NS_IMETHOD              ResizeClient(PRInt32 aWidth, PRInt32 aHeight, bool aRepaint);
   NS_IMETHOD              ResizeClient(PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight, bool aRepaint);
@@ -263,16 +278,19 @@ protected:
 protected:
   void*             mClientData;
   ViewWrapper*      mViewWrapperPtr;
   EVENT_CALLBACK    mEventCallback;
   EVENT_CALLBACK    mViewCallback;
   nsDeviceContext* mContext;
   nsRefPtr<LayerManager> mLayerManager;
   nsRefPtr<LayerManager> mBasicLayerManager;
+  nsRefPtr<CompositorChild> mCompositorChild;
+  nsRefPtr<CompositorParent> mCompositorParent;
+  Thread*           mCompositorThread;
   nscolor           mBackground;
   nscolor           mForeground;
   nsCursor          mCursor;
   nsWindowType      mWindowType;
   nsBorderStyle     mBorderStyle;
   bool              mOnDestroyCalled;
   bool              mUseAcceleratedRendering;
   bool              mTemporarilyUseBasicLayerManager;