Move CompositorWidgetProxy inheritance out of nsIWidget. (bug 1264545 part 6, r=jimm)
authorDavid Anderson <danderson@mozilla.com>
Fri, 29 Apr 2016 19:23:17 -0400
changeset 358098 304b1365d2d73af93e87322caaaca0ff148b31ef
parent 358097 b45b6eca1e7b239197945e0966674979731834ba
child 358099 d07106878066a0d6a95336c71435b9d3e759a876
push id16941
push userbmo:jbeich@FreeBSD.org
push dateSun, 01 May 2016 11:16:34 +0000
reviewersjimm
bugs1264545
milestone49.0a1
Move CompositorWidgetProxy inheritance out of nsIWidget. (bug 1264545 part 6, r=jimm)
gfx/layers/Compositor.h
gfx/tests/gtest/TestCompositor.cpp
layout/forms/nsMeterFrame.h
widget/CompositorWidgetProxy.cpp
widget/CompositorWidgetProxy.h
widget/PuppetWidget.h
widget/android/nsWindow.cpp
widget/android/nsWindow.h
widget/cocoa/nsChildView.mm
widget/cocoa/nsCocoaWindow.h
widget/moz.build
widget/nsBaseWidget.cpp
widget/nsBaseWidget.h
widget/nsIWidget.h
widget/windows/nsWindow.h
--- a/gfx/layers/Compositor.h
+++ b/gfx/layers/Compositor.h
@@ -16,16 +16,17 @@
 #include "mozilla/gfx/Types.h"          // for Float
 #include "mozilla/layers/CompositorTypes.h"  // for DiagnosticTypes, etc
 #include "mozilla/layers/FenceUtils.h"  // for FenceHandle
 #include "mozilla/layers/LayersTypes.h"  // for LayersBackend
 #include "nsISupportsImpl.h"            // for MOZ_COUNT_CTOR, etc
 #include "nsRegion.h"
 #include <vector>
 #include "mozilla/WidgetUtils.h"
+#include "CompositorWidgetProxy.h"
 
 /**
  * Different elements of a web pages are rendered into separate "layers" before
  * they are flattened into the final image that is brought to the screen.
  * See Layers.h for more informations about layers and why we use retained
  * structures.
  * Most of the documentation for layers is directly in the source code in the
  * form of doc comments. An overview can also be found in the the wiki:
--- a/gfx/tests/gtest/TestCompositor.cpp
+++ b/gfx/tests/gtest/TestCompositor.cpp
@@ -82,35 +82,41 @@ public:
   virtual LayoutDeviceIntPoint WidgetToScreenOffset() override { return LayoutDeviceIntPoint(0, 0); }
   NS_IMETHOD              DispatchEvent(mozilla::WidgetGUIEvent* aEvent,
                                         nsEventStatus& aStatus) override { return NS_OK; }
   NS_IMETHOD              CaptureRollupEvents(nsIRollupListener * aListener, bool aDoCapture) override { return NS_OK; }
   NS_IMETHOD_(void)       SetInputContext(const InputContext& aContext,
                                           const InputContextAction& aAction) override {}
   NS_IMETHOD_(InputContext) GetInputContext() override { abort(); }
   NS_IMETHOD              ReparentNativeWidget(nsIWidget* aNewParent) override { return NS_OK; }
+
 private:
   ~MockWidget() {}
 };
 
 NS_IMPL_ISUPPORTS_INHERITED0(MockWidget, nsBaseWidget)
 
 struct LayerManagerData {
   RefPtr<MockWidget> mWidget;
   RefPtr<Compositor> mCompositor;
+  RefPtr<widget::CompositorWidgetProxy> mCompositorWidgetProxy;
   RefPtr<LayerManagerComposite> mLayerManager;
 
-  LayerManagerData(Compositor* compositor, MockWidget* widget, LayerManagerComposite* layerManager)
+  LayerManagerData(Compositor* compositor,
+                   MockWidget* widget,
+                   widget::CompositorWidgetProxy* aProxy,
+                   LayerManagerComposite* layerManager)
     : mWidget(widget)
     , mCompositor(compositor)
+    , mCompositorWidgetProxy(aProxy)
     , mLayerManager(layerManager)
   {}
 };
 
-static already_AddRefed<Compositor> CreateTestCompositor(LayersBackend backend, MockWidget* widget)
+static already_AddRefed<Compositor> CreateTestCompositor(LayersBackend backend, widget::CompositorWidgetProxy* widget)
 {
   gfxPrefs::GetSingleton();
 
   RefPtr<Compositor> compositor;
 
   if (backend == LayersBackend::LAYERS_OPENGL) {
     compositor = new CompositorOGL(nullptr,
                                    widget,
@@ -144,21 +150,22 @@ static already_AddRefed<Compositor> Crea
 static std::vector<LayerManagerData> GetLayerManagers(std::vector<LayersBackend> aBackends)
 {
   std::vector<LayerManagerData> managers;
 
   for (size_t i = 0; i < aBackends.size(); i++) {
     auto backend = aBackends[i];
 
     RefPtr<MockWidget> widget = new MockWidget();
-    RefPtr<Compositor> compositor = CreateTestCompositor(backend, widget);
+    RefPtr<widget::CompositorWidgetProxy> proxy = widget->NewCompositorWidgetProxy();
+    RefPtr<Compositor> compositor = CreateTestCompositor(backend, proxy);
 
     RefPtr<LayerManagerComposite> layerManager = new LayerManagerComposite(compositor);
 
-    managers.push_back(LayerManagerData(compositor, widget, layerManager));
+    managers.push_back(LayerManagerData(compositor, widget, proxy, layerManager));
   }
 
   return managers;
 }
 
 /**
  * This will return the default list of backends that
  * units test should run against.
--- a/layout/forms/nsMeterFrame.h
+++ b/layout/forms/nsMeterFrame.h
@@ -5,16 +5,17 @@
 
 #ifndef nsMeterFrame_h___
 #define nsMeterFrame_h___
 
 #include "mozilla/Attributes.h"
 #include "nsContainerFrame.h"
 #include "nsIAnonymousContentCreator.h"
 #include "nsCOMPtr.h"
+#include "nsCSSPseudoElements.h"
 
 class nsMeterFrame : public nsContainerFrame,
                      public nsIAnonymousContentCreator
 
 {
   typedef mozilla::dom::Element Element;
 
 public:
@@ -70,17 +71,17 @@ public:
       ~(nsIFrame::eReplaced | nsIFrame::eReplacedContainsBlock));
   }
 
   /**
    * Returns whether the frame and its child should use the native style.
    */
   bool ShouldUseNativeStyle() const;
 
-  virtual Element* GetPseudoElement(CSSPseudoElementType aType) override;
+  virtual Element* GetPseudoElement(mozilla::CSSPseudoElementType aType) override;
 
 protected:
   // Helper function which reflow the anonymous div frame.
   void ReflowBarFrame(nsIFrame*                aBarFrame,
                       nsPresContext*           aPresContext,
                       const nsHTMLReflowState& aReflowState,
                       nsReflowStatus&          aStatus);
   /**
new file mode 100644
--- /dev/null
+++ b/widget/CompositorWidgetProxy.cpp
@@ -0,0 +1,206 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "CompositorWidgetProxy.h"
+#include "GLConsts.h"
+#include "nsBaseWidget.h"
+
+namespace mozilla {
+namespace widget {
+
+CompositorWidgetProxy::~CompositorWidgetProxy()
+{
+}
+
+already_AddRefed<gfx::DrawTarget>
+CompositorWidgetProxy::StartRemoteDrawing()
+{
+  return nullptr;
+}
+
+void
+CompositorWidgetProxy::CleanupRemoteDrawing()
+{
+  mLastBackBuffer = nullptr;
+}
+
+already_AddRefed<gfx::DrawTarget>
+CompositorWidgetProxy::CreateBackBufferDrawTarget(gfx::DrawTarget* aScreenTarget,
+                                                  const LayoutDeviceIntRect& aRect,
+                                                  const LayoutDeviceIntRect& aClearRect)
+{
+  MOZ_ASSERT(aScreenTarget);
+  gfx::SurfaceFormat format = gfx::SurfaceFormat::B8G8R8A8;
+  gfx::IntSize size = aRect.ToUnknownRect().Size();
+  gfx::IntSize clientSize(GetClientSize().ToUnknownSize());
+
+  RefPtr<gfx::DrawTarget> target;
+  // Re-use back buffer if possible
+  if (mLastBackBuffer &&
+      mLastBackBuffer->GetBackendType() == aScreenTarget->GetBackendType() &&
+      mLastBackBuffer->GetFormat() == format &&
+      size <= mLastBackBuffer->GetSize() &&
+      mLastBackBuffer->GetSize() <= clientSize) {
+    target = mLastBackBuffer;
+    target->SetTransform(gfx::Matrix());
+    if (!aClearRect.IsEmpty()) {
+      gfx::IntRect clearRect = aClearRect.ToUnknownRect() - aRect.ToUnknownRect().TopLeft();
+      target->ClearRect(gfx::Rect(clearRect.x, clearRect.y, clearRect.width, clearRect.height));
+    }
+  } else {
+    target = aScreenTarget->CreateSimilarDrawTarget(size, format);
+    mLastBackBuffer = target;
+  }
+  return target.forget();
+}
+
+uint32_t
+CompositorWidgetProxy::GetGLFrameBufferFormat()
+{
+  return LOCAL_GL_RGBA;
+}
+
+CompositorWidgetProxyWrapper::CompositorWidgetProxyWrapper(nsBaseWidget* aWidget)
+ : mWidget(aWidget)
+{
+}
+
+bool
+CompositorWidgetProxyWrapper::PreRender(layers::LayerManagerComposite* aManager)
+{
+  if (!mWidget) {
+    return false;
+  }
+  return mWidget->PreRender(aManager);
+}
+
+void
+CompositorWidgetProxyWrapper::PostRender(layers::LayerManagerComposite* aManager)
+{
+  if (!mWidget) {
+    return;
+  }
+  mWidget->PostRender(aManager);
+}
+
+void
+CompositorWidgetProxyWrapper::DrawWindowUnderlay(layers::LayerManagerComposite* aManager,
+                                                 LayoutDeviceIntRect aRect)
+{
+  if (!mWidget) {
+    return;
+  }
+  mWidget->DrawWindowUnderlay(aManager, aRect);
+}
+
+void
+CompositorWidgetProxyWrapper::DrawWindowOverlay(layers::LayerManagerComposite* aManager,
+                                                LayoutDeviceIntRect aRect)
+{
+  if (!mWidget) {
+    return;
+  }
+  mWidget->DrawWindowOverlay(aManager, aRect);
+}
+
+already_AddRefed<gfx::DrawTarget>
+CompositorWidgetProxyWrapper::StartRemoteDrawing()
+{
+  if (!mWidget) {
+    return nullptr;
+  }
+  return mWidget->StartRemoteDrawing();
+}
+
+already_AddRefed<gfx::DrawTarget>
+CompositorWidgetProxyWrapper::StartRemoteDrawingInRegion(LayoutDeviceIntRegion& aInvalidRegion,
+                                                         layers::BufferMode* aBufferMode)
+{
+  if (!mWidget) {
+    return nullptr;
+  }
+  return mWidget->StartRemoteDrawingInRegion(aInvalidRegion, aBufferMode);
+}
+
+void
+CompositorWidgetProxyWrapper::EndRemoteDrawing()
+{
+  if (!mWidget) {
+    return;
+  }
+  mWidget->EndRemoteDrawing();
+}
+
+void
+CompositorWidgetProxyWrapper::EndRemoteDrawingInRegion(gfx::DrawTarget* aDrawTarget,
+                                                       LayoutDeviceIntRegion& aInvalidRegion)
+{
+  if (!mWidget) {
+    return;
+  }
+  mWidget->EndRemoteDrawingInRegion(aDrawTarget, aInvalidRegion);
+}
+
+void
+CompositorWidgetProxyWrapper::CleanupRemoteDrawing()
+{
+  if (mWidget) {
+    mWidget->CleanupRemoteDrawing();
+  }
+  CompositorWidgetProxy::CleanupRemoteDrawing();
+}
+
+void
+CompositorWidgetProxyWrapper::CleanupWindowEffects()
+{
+  if (!mWidget) {
+    return;
+  }
+  mWidget->CleanupWindowEffects();
+}
+
+bool
+CompositorWidgetProxyWrapper::InitCompositor(layers::Compositor* aCompositor)
+{
+  if (!mWidget) {
+    return false;
+  }
+  return mWidget->InitCompositor(aCompositor);
+}
+
+LayoutDeviceIntSize
+CompositorWidgetProxyWrapper::GetClientSize()
+{
+  if (!mWidget) {
+    return LayoutDeviceIntSize();
+  }
+  return mWidget->GetClientSize();
+}
+
+uint32_t
+CompositorWidgetProxyWrapper::GetGLFrameBufferFormat()
+{
+  if (!mWidget) {
+    return CompositorWidgetProxy::GetGLFrameBufferFormat();
+  }
+  return mWidget->GetGLFrameBufferFormat();
+}
+
+layers::Composer2D*
+CompositorWidgetProxyWrapper::GetComposer2D()
+{
+  if (!mWidget) {
+    return nullptr;
+  }
+  return mWidget->GetComposer2D();
+}
+
+nsIWidget*
+CompositorWidgetProxyWrapper::RealWidget()
+{
+  return mWidget;
+}
+
+} // namespace widget
+} // namespace mozilla
--- a/widget/CompositorWidgetProxy.h
+++ b/widget/CompositorWidgetProxy.h
@@ -3,16 +3,21 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_widget_CompositorWidgetProxy_h__
 #define mozilla_widget_CompositorWidgetProxy_h__
 
 #include "nsISupports.h"
 #include "mozilla/RefPtr.h"
 #include "Units.h"
+#include "mozilla/gfx/2D.h"
+#include "mozilla/layers/LayersTypes.h"
+
+class nsIWidget;
+class nsBaseWidget;
 
 namespace mozilla {
 namespace layers {
 class Compositor;
 class LayerManagerComposite;
 class Compositor;
 class Composer2D;
 } // namespace layers
@@ -22,16 +27,18 @@ class DrawTarget;
 namespace widget {
 
 /**
  * Access to a widget from the compositor is restricted to these methods.
  */
 class CompositorWidgetProxy
 {
 public:
+  NS_INLINE_DECL_REFCOUNTING(mozilla::widget::CompositorWidgetProxy)
+
   /**
    * Called before rendering using OMTC. Returns false when the widget is
    * not ready to be rendered (for example while the window is closed).
    *
    * Always called from the compositing thread, which may be the main-thread if
    * OMTC is not enabled.
    */
   virtual bool PreRender(layers::LayerManagerComposite* aManager) {
@@ -70,17 +77,17 @@ public:
    * Return a DrawTarget for the window which can be composited into.
    *
    * Called by BasicCompositor on the compositor thread for OMTC drawing
    * before each composition.
    *
    * The window may specify its buffer mode. If unspecified, it is assumed
    * to require double-buffering.
    */
-  virtual already_AddRefed<gfx::DrawTarget> StartRemoteDrawing() = 0;
+  virtual already_AddRefed<gfx::DrawTarget> StartRemoteDrawing();
   virtual already_AddRefed<gfx::DrawTarget>
   StartRemoteDrawingInRegion(LayoutDeviceIntRegion& aInvalidRegion,
                              layers::BufferMode* aBufferMode)
   {
     return StartRemoteDrawing();
   }
 
   /**
@@ -94,40 +101,24 @@ public:
   {}
   virtual void EndRemoteDrawingInRegion(gfx::DrawTarget* aDrawTarget,
                                         LayoutDeviceIntRegion& aInvalidRegion)
   {
     EndRemoteDrawing();
   }
 
   /**
-   * Clean up any resources used by Start/EndRemoteDrawing.
-   *
-   * Called by BasicCompositor on the compositor thread for OMTC drawing
-   * when the compositor is destroyed.
-   */
-  virtual void CleanupRemoteDrawing() = 0;
-
-  /**
    * Called when shutting down the LayerManager to clean-up any cached resources.
    *
    * Always called from the compositing thread.
    */
   virtual void CleanupWindowEffects()
   {}
 
   /**
-   * Create DrawTarget used as BackBuffer of the screen
-   */
-  virtual already_AddRefed<gfx::DrawTarget>
-  CreateBackBufferDrawTarget(gfx::DrawTarget* aScreenTarget,
-                             const LayoutDeviceIntRect& aRect,
-                             const LayoutDeviceIntRect& aClearRect) = 0;
-
-  /**
    * A hook for the widget to prepare a Compositor, during the latter's initialization.
    *
    * If this method returns true, it means that the widget will be able to
    * present frames from the compoositor.
    *
    * Returning false will cause the compositor's initialization to fail, and
    * a different compositor backend will be used (if any).
    */
@@ -139,19 +130,17 @@ public:
    * Return the size of the drawable area of the widget.
    */
   virtual LayoutDeviceIntSize GetClientSize() = 0;
 
   /**
    * Return the internal format of the default framebuffer for this
    * widget.
    */
-  virtual uint32_t GetGLFrameBufferFormat() {
-    return 0; /* GL_NONE */
-  }
+  virtual uint32_t GetGLFrameBufferFormat();
 
   /**
    * If this widget has a more efficient composer available for its
    * native framebuffer, return it.
    *
    * This can be called from a non-main thread, but that thread must
    * hold a strong reference to this.
    */
@@ -159,15 +148,71 @@ public:
     return nullptr;
   }
 
   /*
    * Access the underlying nsIWidget. This method will be removed when the compositor no longer
    * depends on nsIWidget on any platform.
    */
   virtual nsIWidget* RealWidget() = 0;
+
+  /**
+   * Clean up any resources used by Start/EndRemoteDrawing.
+   *
+   * Called by BasicCompositor on the compositor thread for OMTC drawing
+   * when the compositor is destroyed.
+   */
+  virtual void CleanupRemoteDrawing();
+
+  /**
+   * Create a backbuffer for the software compositor.
+   */
+  virtual already_AddRefed<gfx::DrawTarget>
+  CreateBackBufferDrawTarget(gfx::DrawTarget* aScreenTarget,
+                             const LayoutDeviceIntRect& aRect,
+                             const LayoutDeviceIntRect& aClearRect);
+
+protected:
+  virtual ~CompositorWidgetProxy();
+
+private:
+  // Back buffer of BasicCompositor
+  RefPtr<gfx::DrawTarget> mLastBackBuffer;
 };
 
+// This version of CompositorWidgetProxy implements a wrapper around
+// nsBaseWidget.
+class CompositorWidgetProxyWrapper : public CompositorWidgetProxy
+{
+public:
+  explicit CompositorWidgetProxyWrapper(nsBaseWidget* aWidget);
+
+  virtual bool PreRender(layers::LayerManagerComposite* aManager) override;
+  virtual void PostRender(layers::LayerManagerComposite* aManager) override;
+  virtual void DrawWindowUnderlay(layers::LayerManagerComposite* aManager,
+                                  LayoutDeviceIntRect aRect) override;
+  virtual void DrawWindowOverlay(layers::LayerManagerComposite* aManager,
+                                 LayoutDeviceIntRect aRect) override;
+  virtual already_AddRefed<gfx::DrawTarget> StartRemoteDrawing() override;
+  virtual already_AddRefed<gfx::DrawTarget>
+  StartRemoteDrawingInRegion(LayoutDeviceIntRegion& aInvalidRegion,
+                             layers::BufferMode* aBufferMode) override;
+  virtual void EndRemoteDrawing() override;
+  virtual void EndRemoteDrawingInRegion(gfx::DrawTarget* aDrawTarget,
+                                        LayoutDeviceIntRegion& aInvalidRegion) override;
+  virtual void CleanupRemoteDrawing() override;
+  virtual void CleanupWindowEffects() override;
+  virtual bool InitCompositor(layers::Compositor* aCompositor) override;
+  virtual LayoutDeviceIntSize GetClientSize() override;
+  virtual uint32_t GetGLFrameBufferFormat() override;
+  virtual layers::Composer2D* GetComposer2D() override;
+
+  // If you can override this method, inherit from CompositorWidgetProxy instead.
+  nsIWidget* RealWidget() override;
+
+private:
+  nsBaseWidget* mWidget;
+};
 
 } // namespace widget
 } // namespace mozilla
 
 #endif
--- a/widget/PuppetWidget.h
+++ b/widget/PuppetWidget.h
@@ -269,16 +269,22 @@ public:
   virtual nsresult OnWindowedPluginKeyEvent(
                      const NativeEventData& aKeyEventData,
                      nsIKeyEventInPluginCallback* aCallback) override;
 
 protected:
   virtual nsresult NotifyIMEInternal(
                      const IMENotification& aIMENotification) override;
 
+  // PuppetWidgets do not create compositors.
+  widget::CompositorWidgetProxy* NewCompositorWidgetProxy() override {
+    MOZ_ASSERT_UNREACHABLE("PuppetWidgets should not have widget proxies");
+    return nullptr;
+  }
+
 private:
   nsresult Paint();
 
   void SetChild(PuppetWidget* aChild);
 
   nsresult RequestIMEToCommitComposition(bool aCancel);
   nsresult NotifyIMEOfFocusChange(const IMENotification& aIMENotification);
   nsresult NotifyIMEOfSelectionChange(const IMENotification& aIMENotification);
--- a/widget/android/nsWindow.cpp
+++ b/widget/android/nsWindow.cpp
@@ -3545,17 +3545,20 @@ nsWindow::NeedsPaint()
         return false;
     }
     return nsIWidget::NeedsPaint();
 }
 
 CompositorBridgeParent*
 nsWindow::NewCompositorBridgeParent(int aSurfaceWidth, int aSurfaceHeight)
 {
-    return new CompositorBridgeParent(this,
+    if (!mCompositorWidgetProxy) {
+      mCompositorWidgetProxy = NewCompositorWidgetProxy();
+    }
+    return new CompositorBridgeParent(mCompositorWidgetProxy,
                                       GetDefaultScale(),
                                       UseAPZ(),
                                       true,
                                       aSurfaceWidth, aSurfaceHeight);
 }
 
 void
 nsWindow::ConfigureAPZControllerThread()
--- a/widget/android/nsWindow.h
+++ b/widget/android/nsWindow.h
@@ -27,18 +27,17 @@ namespace mozilla {
     namespace layers {
         class CompositorBridgeParent;
         class CompositorBridgeChild;
         class LayerManager;
         class APZCTreeManager;
     }
 }
 
-class nsWindow :
-    public nsBaseWidget
+class nsWindow : public nsBaseWidget
 {
 private:
     virtual ~nsWindow();
 
 public:
     using nsBaseWidget::GetLayerManager;
 
     nsWindow();
--- a/widget/cocoa/nsChildView.mm
+++ b/widget/cocoa/nsChildView.mm
@@ -2657,17 +2657,16 @@ nsChildView::EndRemoteDrawing()
 {
   mBasicCompositorImage->EndUpdate(true);
   DoRemoteComposition(mBounds);
 }
 
 void
 nsChildView::CleanupRemoteDrawing()
 {
-  nsBaseWidget::CleanupRemoteDrawing();
   mBasicCompositorImage = nullptr;
   mCornerMaskImage = nullptr;
   mResizerImage = nullptr;
   mTitlebarImage = nullptr;
   mGLPresenter = nullptr;
 }
 
 bool
--- a/widget/cocoa/nsCocoaWindow.h
+++ b/widget/cocoa/nsCocoaWindow.h
@@ -380,16 +380,21 @@ public:
                         NativeKeyBindingsType aType,
                         const mozilla::WidgetKeyboardEvent& aEvent,
                         DoCommandCallback aCallback,
                         void* aCallbackData) override;
 
     void SetPopupWindowLevel();
 
     NS_IMETHOD         ReparentNativeWidget(nsIWidget* aNewParent) override;
+
+    CompositorWidgetProxy* NewCompositorWidgetProxy() override {
+      return nullptr;
+    }
+
 protected:
   virtual ~nsCocoaWindow();
 
   nsresult             CreateNativeWindow(const NSRect &aRect,
                                           nsBorderStyle aBorderStyle,
                                           bool aRectIsFrameRect);
   nsresult             CreatePopupContentView(const LayoutDeviceIntRect &aRect);
   void                 DestroyNativeWindow();
--- a/widget/moz.build
+++ b/widget/moz.build
@@ -131,16 +131,17 @@ EXPORTS.mozilla += [
 
 EXPORTS.mozilla.widget += [
     'IMEData.h',
     'PuppetBidiKeyboard.h',
     'WidgetMessageUtils.h',
 ]
 
 UNIFIED_SOURCES += [
+    'CompositorWidgetProxy.cpp',
     'ContentCache.cpp',
     'ContentHelper.cpp',
     'GfxDriverInfo.cpp',
     'GfxInfoBase.cpp',
     'GfxInfoCollector.cpp',
     'GfxInfoWebGL.cpp',
     'InputData.cpp',
     'nsBaseAppShell.cpp',
--- a/widget/nsBaseWidget.cpp
+++ b/widget/nsBaseWidget.cpp
@@ -936,17 +936,20 @@ nsBaseWidget::UseAPZ()
   return (gfxPlatform::AsyncPanZoomEnabled() &&
           (WindowType() == eWindowType_toplevel || WindowType() == eWindowType_child));
 }
 
 CompositorBridgeParent*
 nsBaseWidget::NewCompositorBridgeParent(int aSurfaceWidth,
                                         int aSurfaceHeight)
 {
-  return new CompositorBridgeParent(this,
+  if (!mCompositorWidgetProxy) {
+    mCompositorWidgetProxy = NewCompositorWidgetProxy();
+  }
+  return new CompositorBridgeParent(mCompositorWidgetProxy,
                                     GetDefaultScale(),
                                     UseAPZ(),
                                     false,
                                     aSurfaceWidth, aSurfaceHeight);
 }
 
 void nsBaseWidget::CreateCompositor()
 {
@@ -1379,56 +1382,32 @@ LayerManager* nsBaseWidget::CreateBasicL
   return new BasicLayerManager(this);
 }
 
 CompositorBridgeChild* nsBaseWidget::GetRemoteRenderer()
 {
   return mCompositorBridgeChild;
 }
 
-already_AddRefed<mozilla::gfx::DrawTarget>
+already_AddRefed<gfx::DrawTarget>
 nsBaseWidget::StartRemoteDrawing()
 {
   return nullptr;
 }
 
-void
-nsBaseWidget::CleanupRemoteDrawing()
-{
-  mLastBackBuffer = nullptr;
-}
-
-already_AddRefed<mozilla::gfx::DrawTarget>
-nsBaseWidget::CreateBackBufferDrawTarget(mozilla::gfx::DrawTarget* aScreenTarget,
-                                         const LayoutDeviceIntRect& aRect,
-                                         const LayoutDeviceIntRect& aClearRect)
+uint32_t
+nsBaseWidget::GetGLFrameBufferFormat()
 {
-  MOZ_ASSERT(aScreenTarget);
-  gfx::SurfaceFormat format = gfx::SurfaceFormat::B8G8R8A8;
-  gfx::IntSize size = aRect.ToUnknownRect().Size();
-  gfx::IntSize clientSize(GetClientSize().ToUnknownSize());
-
-  RefPtr<gfx::DrawTarget> target;
-  // Re-use back buffer if possible
-  if (mLastBackBuffer &&
-      mLastBackBuffer->GetBackendType() == aScreenTarget->GetBackendType() &&
-      mLastBackBuffer->GetFormat() == format &&
-      size <= mLastBackBuffer->GetSize() &&
-      mLastBackBuffer->GetSize() <= clientSize) {
-    target = mLastBackBuffer;
-    target->SetTransform(gfx::Matrix());
-    if (!aClearRect.IsEmpty()) {
-      gfx::IntRect clearRect = aClearRect.ToUnknownRect() - aRect.ToUnknownRect().TopLeft();
-      target->ClearRect(gfx::Rect(clearRect.x, clearRect.y, clearRect.width, clearRect.height));
-    }
-  } else {
-    target = aScreenTarget->CreateSimilarDrawTarget(size, format);
-    mLastBackBuffer = target;
-  }
-  return target.forget();
+  return LOCAL_GL_RGBA;
+}
+
+mozilla::widget::CompositorWidgetProxy*
+nsBaseWidget::NewCompositorWidgetProxy()
+{
+  return new mozilla::widget::CompositorWidgetProxyWrapper(this);
 }
 
 //-------------------------------------------------------------------------
 //
 // Destroy the window
 //
 //-------------------------------------------------------------------------
 void nsBaseWidget::OnDestroy()
@@ -1703,22 +1682,16 @@ nsBaseWidget::BeginResizeDrag(WidgetGUIE
 }
 
 NS_IMETHODIMP
 nsBaseWidget::BeginMoveDrag(WidgetMouseEvent* aEvent)
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
-uint32_t
-nsBaseWidget::GetGLFrameBufferFormat()
-{
-  return LOCAL_GL_RGBA;
-}
-
 void nsBaseWidget::SetSizeConstraints(const SizeConstraints& aConstraints)
 {
   mSizeConstraints = aConstraints;
   // We can't ensure that the size is honored at this point because we're
   // probably in the middle of a reflow.
 }
 
 const widget::SizeConstraints nsBaseWidget::GetSizeConstraints()
--- a/widget/nsBaseWidget.h
+++ b/widget/nsBaseWidget.h
@@ -16,16 +16,17 @@
 #include "nsIFile.h"
 #include "nsString.h"
 #include "nsCOMPtr.h"
 #include "nsIRollupListener.h"
 #include "nsIObserver.h"
 #include "nsIWidgetListener.h"
 #include "nsPIDOMWindow.h"
 #include "nsWeakReference.h"
+#include "CompositorWidgetProxy.h"
 #include <algorithm>
 class nsIContent;
 class nsAutoRollup;
 class gfxContext;
 
 namespace mozilla {
 #ifdef ACCESSIBILITY
 namespace a11y {
@@ -87,32 +88,34 @@ public:
  * (Note: widget implementations are not required to use this
  * class, but it gives them a head start.)
  */
 
 class nsBaseWidget : public nsIWidget, public nsSupportsWeakReference
 {
   friend class nsAutoRollup;
   friend class DispatchWheelEventOnMainThread;
+  friend class mozilla::widget::CompositorWidgetProxyWrapper;
 
 protected:
   typedef base::Thread Thread;
   typedef mozilla::gfx::DrawTarget DrawTarget;
   typedef mozilla::layers::BasicLayerManager BasicLayerManager;
   typedef mozilla::layers::BufferMode BufferMode;
   typedef mozilla::layers::CompositorBridgeChild CompositorBridgeChild;
   typedef mozilla::layers::CompositorBridgeParent CompositorBridgeParent;
   typedef mozilla::layers::APZCTreeManager APZCTreeManager;
   typedef mozilla::layers::GeckoContentController GeckoContentController;
   typedef mozilla::layers::ScrollableLayerGuid ScrollableLayerGuid;
   typedef mozilla::layers::APZEventState APZEventState;
   typedef mozilla::layers::SetAllowedTouchBehaviorCallback SetAllowedTouchBehaviorCallback;
   typedef mozilla::CSSIntRect CSSIntRect;
   typedef mozilla::CSSRect CSSRect;
   typedef mozilla::ScreenRotation ScreenRotation;
+  typedef mozilla::widget::CompositorWidgetProxy CompositorWidgetProxy;
 
   virtual ~nsBaseWidget();
 
 public:
   nsBaseWidget();
 
   NS_DECL_ISUPPORTS
 
@@ -165,27 +168,16 @@ public:
                                           bool* aAllowRetaining = nullptr) override;
 
   CompositorVsyncDispatcher* GetCompositorVsyncDispatcher() override;
   void            CreateCompositorVsyncDispatcher();
   virtual CompositorBridgeParent* NewCompositorBridgeParent(int aSurfaceWidth, int aSurfaceHeight);
   virtual void            CreateCompositor();
   virtual void            CreateCompositor(int aWidth, int aHeight);
   virtual void            PrepareWindowEffects() override {}
-  virtual void            CleanupWindowEffects() override {}
-  virtual bool            PreRender(LayerManagerComposite* aManager) override { return true; }
-  virtual void            PostRender(LayerManagerComposite* aManager) override {}
-  virtual void            DrawWindowUnderlay(LayerManagerComposite* aManager, LayoutDeviceIntRect aRect) override {}
-  virtual void            DrawWindowOverlay(LayerManagerComposite* aManager, LayoutDeviceIntRect aRect) override {}
-  virtual already_AddRefed<mozilla::gfx::DrawTarget> StartRemoteDrawing() override;
-  virtual void            EndRemoteDrawing() override { };
-  virtual void            CleanupRemoteDrawing() override;
-  virtual already_AddRefed<mozilla::gfx::DrawTarget> CreateBackBufferDrawTarget(mozilla::gfx::DrawTarget* aScreenTarget,
-                                                                                const LayoutDeviceIntRect& aRect,
-                                                                                const LayoutDeviceIntRect& aClearRect) override;
   virtual void            UpdateThemeGeometries(const nsTArray<ThemeGeometry>& aThemeGeometries) override {}
   NS_IMETHOD              SetModal(bool aModal) override;
   virtual uint32_t        GetMaxTouchPoints() const override;
   NS_IMETHOD              SetWindowClass(const nsAString& xulWinType) override;
   virtual nsresult        SetWindowClipRegion(const nsTArray<LayoutDeviceIntRect>& aRects, bool aIntersectWithExisting) override;
   // Return whether this widget interprets parameters to Move and Resize APIs
   // as "desktop pixels" rather than "device pixels", and therefore
   // applies its GetDefaultScale() value to them before using them as mBounds
@@ -315,18 +307,16 @@ public:
   {
     return (mWindowType == eWindowType_popup && 
             mBorderStyle != eBorderStyle_default &&
             mBorderStyle & eBorderStyle_title);
   }
 
   NS_IMETHOD              ReparentNativeWidget(nsIWidget* aNewParent) override = 0;
 
-  virtual uint32_t GetGLFrameBufferFormat() override;
-
   virtual const SizeConstraints GetSizeConstraints() override;
   virtual void SetSizeConstraints(const SizeConstraints& aConstraints) override;
 
   virtual void StartAsyncScrollbarDrag(const AsyncDragMetrics& aDragMetrics) override;
 
   /**
    * Use this when GetLayerManager() returns a BasicLayerManager
    * (nsBaseWidget::GetLayerManager() does). This sets up the widget's
@@ -350,22 +340,60 @@ public:
   friend class AutoLayerManagerSetup;
 
   virtual bool            ShouldUseOffMainThreadCompositing();
 
   static nsIRollupListener* GetActiveRollupListener();
 
   void Shutdown();
 
-  virtual nsIWidget* RealWidget() override {
-    return this;
+  // Return a new CompositorWidgetProxy for this widget.
+  virtual CompositorWidgetProxy* NewCompositorWidgetProxy();
+
+protected:
+  // These are methods for CompositorWidgetProxyWrapper, and should only be
+  // accessed from that class. Derived widgets can choose which methods to
+  // implement, or none if supporting out-of-process compositing.
+  virtual bool PreRender(mozilla::layers::LayerManagerComposite* aManager) {
+    return true;
+  }
+  virtual void PostRender(mozilla::layers::LayerManagerComposite* aManager)
+  {}
+  virtual void DrawWindowUnderlay(mozilla::layers::LayerManagerComposite* aManager,
+                                  LayoutDeviceIntRect aRect)
+  {}
+  virtual void DrawWindowOverlay(mozilla::layers::LayerManagerComposite* aManager,
+                                 LayoutDeviceIntRect aRect)
+  {}
+  virtual already_AddRefed<DrawTarget> StartRemoteDrawing();
+  virtual already_AddRefed<DrawTarget>
+  StartRemoteDrawingInRegion(LayoutDeviceIntRegion& aInvalidRegion, BufferMode* aBufferMode)
+  {
+    return StartRemoteDrawing();
+  }
+  virtual void EndRemoteDrawing()
+  {}
+  virtual void EndRemoteDrawingInRegion(DrawTarget* aDrawTarget,
+                                        LayoutDeviceIntRegion& aInvalidRegion)
+  {
+    EndRemoteDrawing();
+  }
+  virtual void CleanupRemoteDrawing()
+  {}
+  virtual void CleanupWindowEffects()
+  {}
+  virtual bool InitCompositor(mozilla::layers::Compositor* aCompositor) {
+    return true;
+  }
+  virtual uint32_t GetGLFrameBufferFormat();
+  virtual mozilla::layers::Composer2D* GetComposer2D() {
+    return nullptr;
   }
 
 protected:
-
   void            ResolveIconName(const nsAString &aIconName,
                                   const nsAString &aIconSuffix,
                                   nsIFile **aResult);
   virtual void    OnDestroy();
   void            BaseCreate(nsIWidget *aParent,
                              nsWidgetInitData* aInitData);
 
   virtual void ConfigureAPZCTreeManager();
@@ -496,17 +524,17 @@ protected:
   /**
    * Notify the widget that this window is being used with OMTC.
    */
   virtual void WindowUsesOMTC() {}
   virtual void RegisterTouchWindow() {}
 
   nsIDocument* GetDocument() const;
 
- void EnsureTextEventDispatcher();
+  void EnsureTextEventDispatcher();
 
   // Notify the compositor that a device reset has occurred.
   void OnRenderingDeviceReset();
 
   bool UseAPZ();
 
 protected:
   /**
@@ -528,33 +556,33 @@ protected:
   nsIWidgetListener* mPreviouslyAttachedWidgetListener;
   RefPtr<LayerManager> mLayerManager;
   RefPtr<CompositorBridgeChild> mCompositorBridgeChild;
   RefPtr<CompositorBridgeParent> mCompositorBridgeParent;
   RefPtr<mozilla::CompositorVsyncDispatcher> mCompositorVsyncDispatcher;
   RefPtr<APZCTreeManager> mAPZC;
   RefPtr<GeckoContentController> mRootContentController;
   RefPtr<APZEventState> mAPZEventState;
-  // Back buffer of BasicCompositor
-  RefPtr<DrawTarget> mLastBackBuffer;
   SetAllowedTouchBehaviorCallback mSetAllowedTouchBehaviorCallback;
   RefPtr<WidgetShutdownObserver> mShutdownObserver;
   RefPtr<TextEventDispatcher> mTextEventDispatcher;
   nsCursor          mCursor;
   nsBorderStyle     mBorderStyle;
   LayoutDeviceIntRect mBounds;
   LayoutDeviceIntRect* mOriginalBounds;
   // When this pointer is null, the widget is not clipped
   mozilla::UniquePtr<LayoutDeviceIntRect[]> mClipRects;
   uint32_t          mClipRectCount;
   nsSizeMode        mSizeMode;
   nsPopupLevel      mPopupLevel;
   nsPopupType       mPopupType;
   SizeConstraints   mSizeConstraints;
 
+  RefPtr<CompositorWidgetProxy> mCompositorWidgetProxy;
+
   bool              mUpdateCursor;
   bool              mUseAttachedEvents;
   bool              mIMEHasFocus;
 #if defined(XP_WIN) || defined(XP_MACOSX)
   bool              mAccessibilityInUseFlag;
 #endif
   static nsIRollupListener* gRollupListener;
 
--- a/widget/nsIWidget.h
+++ b/widget/nsIWidget.h
@@ -26,17 +26,16 @@
 #include "mozilla/TimeStamp.h"
 #include "mozilla/gfx/Point.h"
 #include "mozilla/widget/IMEData.h"
 #include "nsDataHashtable.h"
 #include "nsIObserver.h"
 #include "nsIWidgetListener.h"
 #include "FrameMetrics.h"
 #include "Units.h"
-#include "CompositorWidgetProxy.h"
 
 // forward declarations
 class   nsIRollupListener;
 class   imgIContainer;
 class   nsIContent;
 class   ViewWrapper;
 class   nsIScreen;
 class   nsIRunnable;
@@ -318,19 +317,17 @@ private:
 
 } // namespace widget
 } // namespace mozilla
 
 /**
  * The base class for all the widgets. It provides the interface for
  * all basic and necessary functionality.
  */
-class nsIWidget
-  : public nsISupports,
-    public mozilla::widget::CompositorWidgetProxy
+class nsIWidget : public nsISupports
 {
   protected:
     typedef mozilla::dom::TabChild TabChild;
 
   public:
     typedef mozilla::layers::Composer2D Composer2D;
     typedef mozilla::layers::CompositorBridgeChild CompositorBridgeChild;
     typedef mozilla::layers::AsyncDragMetrics AsyncDragMetrics;
--- a/widget/windows/nsWindow.h
+++ b/widget/windows/nsWindow.h
@@ -489,16 +489,17 @@ protected:
   static bool             IsTopLevelMouseExit(HWND aWnd);
   virtual nsresult        SetWindowClipRegion(const nsTArray<LayoutDeviceIntRect>& aRects,
                                               bool aIntersectWithExisting) override;
   nsIntRegion             GetRegionToPaint(bool aForceFullRepaint, 
                                            PAINTSTRUCT ps, HDC aDC);
   static void             ActivateOtherWindowHelper(HWND aWnd);
   void                    ClearCachedResources();
   nsIWidgetListener*      GetPaintListener();
+
   virtual bool            PreRender(LayerManagerComposite*) override;
   virtual void            PostRender(LayerManagerComposite*) override;
 
 protected:
   nsCOMPtr<nsIWidget>   mParent;
   nsIntSize             mLastSize;
   nsIntPoint            mLastPoint;
   HWND                  mWnd;