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 295585 304b1365d2d73af93e87322caaaca0ff148b31ef
parent 295584 b45b6eca1e7b239197945e0966674979731834ba
child 295586 d07106878066a0d6a95336c71435b9d3e759a876
push id30226
push usercbook@mozilla.com
push dateMon, 02 May 2016 09:26:03 +0000
treeherdermozilla-central@77cead2cd203 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjimm
bugs1264545
milestone49.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
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;