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 86135 5bd7228ca8a7f416e1cf38adbde530dcdf741f79
parent 86121 622f1d1e7c52e19686f00ff322e9daaf2479326e
child 86136 173c06d3dd71eaa3d791fd402b862275399bf58a
push id805
push userakeybl@mozilla.com
push dateWed, 01 Feb 2012 18:17:35 +0000
treeherdermozilla-aurora@6fb3bf232436 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerscjones
bugs711168
milestone12.0a1
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;