Backed out changeset b1542ac3fc70 (bug 1317893)
authorJerryShih <hshih@mozilla.com>
Fri, 18 Nov 2016 21:56:47 +0800
changeset 459788 c85e2d8dc8df963eb0750cac566f5e91dea17a10
parent 459787 b1542ac3fc7034d6efe289e78e5fe1d5b79aef7e
child 459789 d17759dd3b74426235447bb7ffc3a91b614828b5
push id41343
push userkgupta@mozilla.com
push dateThu, 12 Jan 2017 20:13:44 +0000
bugs1317893
milestone53.0a1
backs outb1542ac3fc7034d6efe289e78e5fe1d5b79aef7e
Backed out changeset b1542ac3fc70 (bug 1317893) Hit assert at: https://hg.mozilla.org/projects/graphics/annotate/b1542ac3fc70/gfx/layers/ipc/CompositorVsyncScheduler.cpp#l85 MozReview-Commit-ID: 612HYIXMgE2
gfx/layers/ipc/CompositorBridgeParent.cpp
gfx/layers/ipc/CompositorBridgeParent.h
gfx/layers/ipc/CompositorVsyncScheduler.cpp
gfx/layers/ipc/CompositorVsyncScheduler.h
gfx/layers/ipc/CrossProcessCompositorBridgeParent.cpp
gfx/layers/moz.build
gfx/layers/wr/WebRenderBridgeParent.cpp
gfx/layers/wr/WebRenderBridgeParent.h
gfx/webrender/src/bindings.rs
--- a/gfx/layers/ipc/CompositorBridgeParent.cpp
+++ b/gfx/layers/ipc/CompositorBridgeParent.cpp
@@ -277,16 +277,318 @@ CalculateCompositionFrameRate()
       return defaultFrameRate;
     }
     return layoutFrameRatePref;
   }
   return compositionFrameRatePref;
 }
 #endif
 
+CompositorVsyncScheduler::Observer::Observer(CompositorVsyncScheduler* aOwner)
+  : mMutex("CompositorVsyncScheduler.Observer.Mutex")
+  , mOwner(aOwner)
+{
+}
+
+CompositorVsyncScheduler::Observer::~Observer()
+{
+  MOZ_ASSERT(!mOwner);
+}
+
+bool
+CompositorVsyncScheduler::Observer::NotifyVsync(TimeStamp aVsyncTimestamp)
+{
+  MutexAutoLock lock(mMutex);
+  if (!mOwner) {
+    return false;
+  }
+  return mOwner->NotifyVsync(aVsyncTimestamp);
+}
+
+void
+CompositorVsyncScheduler::Observer::Destroy()
+{
+  MutexAutoLock lock(mMutex);
+  mOwner = nullptr;
+}
+
+CompositorVsyncScheduler::CompositorVsyncScheduler(CompositorBridgeParent* aCompositorBridgeParent,
+                                                   widget::CompositorWidget* aWidget)
+  : mCompositorBridgeParent(aCompositorBridgeParent)
+  , mLastCompose(TimeStamp::Now())
+  , mIsObservingVsync(false)
+  , mNeedsComposite(0)
+  , mVsyncNotificationsSkipped(0)
+  , mWidget(aWidget)
+  , mCurrentCompositeTaskMonitor("CurrentCompositeTaskMonitor")
+  , mCurrentCompositeTask(nullptr)
+  , mSetNeedsCompositeMonitor("SetNeedsCompositeMonitor")
+  , mSetNeedsCompositeTask(nullptr)
+{
+  MOZ_ASSERT(NS_IsMainThread() || XRE_GetProcessType() == GeckoProcessType_GPU);
+  mVsyncObserver = new Observer(this);
+
+  // mAsapScheduling is set on the main thread during init,
+  // but is only accessed after on the compositor thread.
+  mAsapScheduling = gfxPrefs::LayersCompositionFrameRate() == 0 ||
+                    gfxPlatform::IsInLayoutAsapMode();
+}
+
+CompositorVsyncScheduler::~CompositorVsyncScheduler()
+{
+  MOZ_ASSERT(!mIsObservingVsync);
+  MOZ_ASSERT(!mVsyncObserver);
+  // The CompositorVsyncDispatcher is cleaned up before this in the nsBaseWidget, which stops vsync listeners
+  mCompositorBridgeParent = nullptr;
+}
+
+void
+CompositorVsyncScheduler::Destroy()
+{
+  if (!mVsyncObserver) {
+    // Destroy was already called on this object.
+    return;
+  }
+  MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
+  UnobserveVsync();
+  mVsyncObserver->Destroy();
+  mVsyncObserver = nullptr;
+
+  CancelCurrentSetNeedsCompositeTask();
+  CancelCurrentCompositeTask();
+}
+
+void
+CompositorVsyncScheduler::PostCompositeTask(TimeStamp aCompositeTimestamp)
+{
+  // can be called from the compositor or vsync thread
+  MonitorAutoLock lock(mCurrentCompositeTaskMonitor);
+  if (mCurrentCompositeTask == nullptr && CompositorThreadHolder::Loop()) {
+    RefPtr<CancelableRunnable> task =
+      NewCancelableRunnableMethod<TimeStamp>(this, &CompositorVsyncScheduler::Composite,
+                                             aCompositeTimestamp);
+    mCurrentCompositeTask = task;
+    ScheduleTask(task.forget(), 0);
+  }
+}
+
+void
+CompositorVsyncScheduler::ScheduleComposition()
+{
+  MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
+  if (mAsapScheduling) {
+    // Used only for performance testing purposes
+    PostCompositeTask(TimeStamp::Now());
+#ifdef MOZ_WIDGET_ANDROID
+  } else if (mNeedsComposite >= 2 && mIsObservingVsync) {
+    // uh-oh, we already requested a composite at least twice so far, and a
+    // composite hasn't happened yet. It is possible that the vsync observation
+    // is blocked on the main thread, so let's just composite ASAP and not
+    // wait for the vsync. Note that this should only ever happen on Fennec
+    // because there content runs in the same process as the compositor, and so
+    // content can actually block the main thread in this process.
+    PostCompositeTask(TimeStamp::Now());
+#endif
+  } else {
+    SetNeedsComposite();
+  }
+}
+
+void
+CompositorVsyncScheduler::CancelCurrentSetNeedsCompositeTask()
+{
+  MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
+  MonitorAutoLock lock(mSetNeedsCompositeMonitor);
+  if (mSetNeedsCompositeTask) {
+    mSetNeedsCompositeTask->Cancel();
+    mSetNeedsCompositeTask = nullptr;
+  }
+  mNeedsComposite = 0;
+}
+
+/**
+ * TODO Potential performance heuristics:
+ * If a composite takes 17 ms, do we composite ASAP or wait until next vsync?
+ * If a layer transaction comes after vsync, do we composite ASAP or wait until
+ * next vsync?
+ * How many skipped vsync events until we stop listening to vsync events?
+ */
+void
+CompositorVsyncScheduler::SetNeedsComposite()
+{
+  if (!CompositorThreadHolder::IsInCompositorThread()) {
+    MonitorAutoLock lock(mSetNeedsCompositeMonitor);
+    RefPtr<CancelableRunnable> task =
+      NewCancelableRunnableMethod(this, &CompositorVsyncScheduler::SetNeedsComposite);
+    mSetNeedsCompositeTask = task;
+    ScheduleTask(task.forget(), 0);
+    return;
+  } else {
+    MonitorAutoLock lock(mSetNeedsCompositeMonitor);
+    mSetNeedsCompositeTask = nullptr;
+  }
+
+  mNeedsComposite++;
+  if (!mIsObservingVsync && mNeedsComposite) {
+    ObserveVsync();
+  }
+}
+
+bool
+CompositorVsyncScheduler::NotifyVsync(TimeStamp aVsyncTimestamp)
+{
+  // Called from the vsync dispatch thread. When in the GPU Process, that's
+  // the same as the compositor thread.
+  MOZ_ASSERT_IF(XRE_IsParentProcess(), !CompositorThreadHolder::IsInCompositorThread());
+  MOZ_ASSERT_IF(XRE_GetProcessType() == GeckoProcessType_GPU, CompositorThreadHolder::IsInCompositorThread());
+  MOZ_ASSERT(!NS_IsMainThread());
+  PostCompositeTask(aVsyncTimestamp);
+  return true;
+}
+
+void
+CompositorVsyncScheduler::CancelCurrentCompositeTask()
+{
+  MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread() || NS_IsMainThread());
+  MonitorAutoLock lock(mCurrentCompositeTaskMonitor);
+  if (mCurrentCompositeTask) {
+    mCurrentCompositeTask->Cancel();
+    mCurrentCompositeTask = nullptr;
+  }
+}
+
+void
+CompositorVsyncScheduler::Composite(TimeStamp aVsyncTimestamp)
+{
+  MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
+  {
+    MonitorAutoLock lock(mCurrentCompositeTaskMonitor);
+    mCurrentCompositeTask = nullptr;
+  }
+
+  if ((aVsyncTimestamp < mLastCompose) && !mAsapScheduling) {
+    // We can sometimes get vsync timestamps that are in the past
+    // compared to the last compose with force composites.
+    // In those cases, wait until the next vsync;
+    return;
+  }
+
+  MOZ_ASSERT(mCompositorBridgeParent);
+  if (!mAsapScheduling && mCompositorBridgeParent->IsPendingComposite()) {
+    // If previous composite is still on going, finish it and does a next
+    // composite in a next vsync.
+    mCompositorBridgeParent->FinishPendingComposite();
+    return;
+  }
+
+  DispatchTouchEvents(aVsyncTimestamp);
+  DispatchVREvents(aVsyncTimestamp);
+
+  if (mNeedsComposite || mAsapScheduling) {
+    mNeedsComposite = 0;
+    mLastCompose = aVsyncTimestamp;
+    ComposeToTarget(nullptr);
+    mVsyncNotificationsSkipped = 0;
+
+    TimeDuration compositeFrameTotal = TimeStamp::Now() - aVsyncTimestamp;
+    mozilla::Telemetry::Accumulate(mozilla::Telemetry::COMPOSITE_FRAME_ROUNDTRIP_TIME,
+                                   compositeFrameTotal.ToMilliseconds());
+  } else if (mVsyncNotificationsSkipped++ > gfxPrefs::CompositorUnobserveCount()) {
+    UnobserveVsync();
+  }
+}
+
+void
+CompositorVsyncScheduler::OnForceComposeToTarget()
+{
+  /**
+   * bug 1138502 - There are cases such as during long-running window resizing events
+   * where we receive many sync RecvFlushComposites. We also get vsync notifications which
+   * will increment mVsyncNotificationsSkipped because a composite just occurred. After
+   * enough vsyncs and RecvFlushComposites occurred, we will disable vsync. Then at the next
+   * ScheduleComposite, we will enable vsync, then get a RecvFlushComposite, which will
+   * force us to unobserve vsync again. On some platforms, enabling/disabling vsync is not
+   * free and this oscillating behavior causes a performance hit. In order to avoid this problem,
+   * we reset the mVsyncNotificationsSkipped counter to keep vsync enabled.
+   */
+  MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
+  mVsyncNotificationsSkipped = 0;
+}
+
+void
+CompositorVsyncScheduler::ForceComposeToTarget(gfx::DrawTarget* aTarget, const IntRect* aRect)
+{
+  MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
+  OnForceComposeToTarget();
+  mLastCompose = TimeStamp::Now();
+  ComposeToTarget(aTarget, aRect);
+}
+
+bool
+CompositorVsyncScheduler::NeedsComposite()
+{
+  MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
+  return mNeedsComposite;
+}
+
+void
+CompositorVsyncScheduler::ObserveVsync()
+{
+  MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
+  mWidget->ObserveVsync(mVsyncObserver);
+  mIsObservingVsync = true;
+}
+
+void
+CompositorVsyncScheduler::UnobserveVsync()
+{
+  MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
+  mWidget->ObserveVsync(nullptr);
+  mIsObservingVsync = false;
+}
+
+void
+CompositorVsyncScheduler::DispatchTouchEvents(TimeStamp aVsyncTimestamp)
+{
+}
+
+void
+CompositorVsyncScheduler::DispatchVREvents(TimeStamp aVsyncTimestamp)
+{
+  MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
+
+  VRManager* vm = VRManager::Get();
+  vm->NotifyVsync(aVsyncTimestamp);
+}
+
+void
+CompositorVsyncScheduler::ScheduleTask(already_AddRefed<CancelableRunnable> aTask,
+                                       int aTime)
+{
+  MOZ_ASSERT(CompositorThreadHolder::Loop());
+  MOZ_ASSERT(aTime >= 0);
+  CompositorThreadHolder::Loop()->PostDelayedTask(Move(aTask), aTime);
+}
+
+void
+CompositorVsyncScheduler::ResumeComposition()
+{
+  MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
+  mLastCompose = TimeStamp::Now();
+  ComposeToTarget(nullptr);
+}
+
+void
+CompositorVsyncScheduler::ComposeToTarget(gfx::DrawTarget* aTarget, const IntRect* aRect)
+{
+  MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
+  MOZ_ASSERT(mCompositorBridgeParent);
+  mCompositorBridgeParent->CompositeToTarget(aTarget, aRect);
+}
+
 static inline MessageLoop*
 CompositorLoop()
 {
   return CompositorThreadHolder::Loop();
 }
 
 CompositorBridgeParent::CompositorBridgeParent(CSSToLayoutDeviceScale aScale,
                                                const TimeDuration& aVsyncRate,
@@ -1547,17 +1849,17 @@ CompositorBridgeParent::AllocPWebRenderB
   // Extra guard since this in the parent process and we don't want a malicious
   // child process invoking this codepath before it's ready
   MOZ_RELEASE_ASSERT(false);
 #endif
   MOZ_ASSERT(aPipelineId == mRootLayerTreeID);
 
   RefPtr<gl::GLContext> glc(gl::GLContextProvider::CreateForCompositorWidget(mWidget, true));
   RefPtr<Compositor> compositor = new WebRenderCompositorOGL(glc.get());
-  WebRenderBridgeParent* parent = new WebRenderBridgeParent(nullptr, aPipelineId,
+  WebRenderBridgeParent* parent = new WebRenderBridgeParent(aPipelineId,
         &aResourcePath, mWidget, glc.get(), nullptr, compositor.get());
   parent->AddRef(); // IPDL reference
   MonitorAutoLock lock(*sIndirectLayerTreesLock);
   MOZ_ASSERT(sIndirectLayerTrees[aPipelineId].mWRBridge == nullptr);
   sIndirectLayerTrees[aPipelineId].mWRBridge = parent;
   return parent;
 }
 
--- a/gfx/layers/ipc/CompositorBridgeParent.h
+++ b/gfx/layers/ipc/CompositorBridgeParent.h
@@ -23,26 +23,26 @@
 #include "mozilla/Monitor.h"            // for Monitor
 #include "mozilla/RefPtr.h"             // for RefPtr
 #include "mozilla/TimeStamp.h"          // for TimeStamp
 #include "mozilla/dom/ipc/IdType.h"
 #include "mozilla/gfx/Point.h"          // for IntSize
 #include "mozilla/ipc/ProtocolUtils.h"
 #include "mozilla/ipc/SharedMemory.h"
 #include "mozilla/layers/CompositorController.h"
-#include "mozilla/layers/CompositorVsyncScheduler.h"
 #include "mozilla/layers/GeckoContentController.h"
 #include "mozilla/layers/ISurfaceAllocator.h" // for ShmemAllocator
 #include "mozilla/layers/LayersMessages.h"  // for TargetConfig
 #include "mozilla/layers/MetricsSharingController.h"
 #include "mozilla/layers/PCompositorBridgeParent.h"
 #include "mozilla/layers/APZTestData.h"
 #include "mozilla/widget/CompositorWidget.h"
 #include "nsISupportsImpl.h"
 #include "ThreadSafeRefcountingWithMainThreadDestruction.h"
+#include "mozilla/VsyncDispatcher.h"
 
 class MessageLoop;
 class nsIWidget;
 
 namespace mozilla {
 
 class CancelableRunnable;
 
@@ -78,16 +78,101 @@ struct ScopedLayerTreeRegistration
                               Layer* aRoot,
                               GeckoContentController* aController);
   ~ScopedLayerTreeRegistration();
 
 private:
   uint64_t mLayersId;
 };
 
+/**
+ * Manages the vsync (de)registration and tracking on behalf of the
+ * compositor when it need to paint.
+ * Turns vsync notifications into scheduled composites.
+ **/
+class CompositorVsyncScheduler
+{
+  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CompositorVsyncScheduler)
+
+public:
+  explicit CompositorVsyncScheduler(CompositorBridgeParent* aCompositorBridgeParent,
+                                    widget::CompositorWidget* aWidget);
+
+  bool NotifyVsync(TimeStamp aVsyncTimestamp);
+  void SetNeedsComposite();
+  void OnForceComposeToTarget();
+
+  void ScheduleTask(already_AddRefed<CancelableRunnable>, int);
+  void ResumeComposition();
+  void ComposeToTarget(gfx::DrawTarget* aTarget, const gfx::IntRect* aRect = nullptr);
+  void PostCompositeTask(TimeStamp aCompositeTimestamp);
+  void Destroy();
+  void ScheduleComposition();
+  void CancelCurrentCompositeTask();
+  bool NeedsComposite();
+  void Composite(TimeStamp aVsyncTimestamp);
+  void ForceComposeToTarget(gfx::DrawTarget* aTarget, const gfx::IntRect* aRect);
+
+  const TimeStamp& GetLastComposeTime()
+  {
+    return mLastCompose;
+  }
+
+#ifdef COMPOSITOR_PERFORMANCE_WARNING
+  const TimeStamp& GetExpectedComposeStartTime()
+  {
+    return mExpectedComposeStartTime;
+  }
+#endif
+
+private:
+  virtual ~CompositorVsyncScheduler();
+
+  void NotifyCompositeTaskExecuted();
+  void ObserveVsync();
+  void UnobserveVsync();
+  void DispatchTouchEvents(TimeStamp aVsyncTimestamp);
+  void DispatchVREvents(TimeStamp aVsyncTimestamp);
+  void CancelCurrentSetNeedsCompositeTask();
+
+  class Observer final : public VsyncObserver
+  {
+  public:
+    explicit Observer(CompositorVsyncScheduler* aOwner);
+    virtual bool NotifyVsync(TimeStamp aVsyncTimestamp) override;
+    void Destroy();
+  private:
+    virtual ~Observer();
+
+    Mutex mMutex;
+    // Hold raw pointer to avoid mutual reference.
+    CompositorVsyncScheduler* mOwner;
+  };
+
+  CompositorBridgeParent* mCompositorBridgeParent;
+  TimeStamp mLastCompose;
+
+#ifdef COMPOSITOR_PERFORMANCE_WARNING
+  TimeStamp mExpectedComposeStartTime;
+#endif
+
+  bool mAsapScheduling;
+  bool mIsObservingVsync;
+  uint32_t mNeedsComposite;
+  int32_t mVsyncNotificationsSkipped;
+  widget::CompositorWidget* mWidget;
+  RefPtr<CompositorVsyncScheduler::Observer> mVsyncObserver;
+
+  mozilla::Monitor mCurrentCompositeTaskMonitor;
+  RefPtr<CancelableRunnable> mCurrentCompositeTask;
+
+  mozilla::Monitor mSetNeedsCompositeMonitor;
+  RefPtr<CancelableRunnable> mSetNeedsCompositeTask;
+};
+
 class CompositorBridgeParentBase : public PCompositorBridgeParent,
                                    public HostIPCAllocator,
                                    public ShmemAllocator,
                                    public MetricsSharingController
 {
 public:
   virtual void ShadowLayersUpdated(LayerTransactionParent* aLayerTree,
                                    const uint64_t& aTransactionId,
@@ -144,18 +229,18 @@ public:
                            uint64_t aLayersId,
                            uint32_t aApzcId) override;
   bool StopSharingMetrics(FrameMetrics::ViewID aScrollId,
                           uint32_t aApzcId) override;
 };
 
 class CompositorBridgeParent final : public CompositorBridgeParentBase
                                    , public CompositorController
-                                   , public CompositorVsyncSchedulerOwner
 {
+  friend class CompositorVsyncScheduler;
   friend class CompositorThreadHolder;
   friend class InProcessCompositorSession;
   friend class gfx::GPUProcessManager;
   friend class gfx::GPUParent;
 
 public:
   NS_IMETHOD_(MozExternalRefCountType) AddRef() override { return CompositorBridgeParentBase::AddRef(); }
   NS_IMETHOD_(MozExternalRefCountType) Release() override { return CompositorBridgeParentBase::Release(); }
@@ -488,31 +573,29 @@ protected:
 
   virtual PLayerTransactionParent*
     AllocPLayerTransactionParent(const nsTArray<LayersBackend>& aBackendHints,
                                  const uint64_t& aId,
                                  TextureFactoryIdentifier* aTextureFactoryIdentifier,
                                  bool* aSuccess) override;
   virtual bool DeallocPLayerTransactionParent(PLayerTransactionParent* aLayers) override;
   virtual void ScheduleTask(already_AddRefed<CancelableRunnable>, int);
+  void CompositeToTarget(gfx::DrawTarget* aTarget, const gfx::IntRect* aRect = nullptr);
 
   void SetEGLSurfaceSize(int width, int height);
 
   void InitializeLayerManager(const nsTArray<LayersBackend>& aBackendHints);
   void PauseComposition();
   void ResumeComposition();
   void ResumeCompositionAndResize(int width, int height);
   void ForceComposition();
   void CancelCurrentCompositeTask();
   void Invalidate();
-
-  // CompositorVsyncSchedulerOwner
-  bool IsPendingComposite() override;
-  void FinishPendingComposite() override;
-  void CompositeToTarget(gfx::DrawTarget* aTarget, const gfx::IntRect* aRect = nullptr) override;
+  bool IsPendingComposite();
+  void FinishPendingComposite();
 
   RefPtr<Compositor> NewCompositor(const nsTArray<LayersBackend>& aBackendHints);
   void ResetCompositorTask(const nsTArray<LayersBackend>& aBackendHints,
                            uint64_t aSeqNo,
                            Maybe<TextureFactoryIdentifier>* aOutNewIdentifier);
   Maybe<TextureFactoryIdentifier> ResetCompositorImpl(const nsTArray<LayersBackend>& aBackendHints);
 
   /**
deleted file mode 100644
--- a/gfx/layers/ipc/CompositorVsyncScheduler.cpp
+++ /dev/null
@@ -1,347 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set sw=2 ts=2 et tw=80 : */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "mozilla/layers/CompositorVsyncScheduler.h"
-
-#include <stdio.h>                      // for fprintf, stdout
-#include <stdint.h>                     // for uint64_t
-#include "base/task.h"                  // for CancelableTask, etc
-#include "base/thread.h"                // for Thread
-#include "gfxPlatform.h"                // for gfxPlatform
-#ifdef MOZ_WIDGET_GTK
-#include "gfxPlatformGtk.h"             // for gfxPlatform
-#endif
-#include "gfxPrefs.h"                   // for gfxPrefs
-#include "mozilla/AutoRestore.h"        // for AutoRestore
-#include "mozilla/DebugOnly.h"          // for DebugOnly
-#include "mozilla/gfx/2D.h"             // for DrawTarget
-#include "mozilla/gfx/Point.h"          // for IntSize
-#include "mozilla/gfx/Rect.h"           // for IntSize
-#include "mozilla/layers/CompositorThread.h"
-#include "mozilla/mozalloc.h"           // for operator new, etc
-#include "nsCOMPtr.h"                   // for already_AddRefed
-#include "nsDebug.h"                    // for NS_ASSERTION, etc
-#include "nsISupportsImpl.h"            // for MOZ_COUNT_CTOR, etc
-#include "nsIWidget.h"                  // for nsIWidget
-#include "nsThreadUtils.h"              // for NS_IsMainThread
-#include "mozilla/Telemetry.h"
-#include "mozilla/VsyncDispatcher.h"
-#if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
-#include "VsyncSource.h"
-#endif
-#include "mozilla/widget/CompositorWidget.h"
-
-namespace mozilla {
-
-namespace layers {
-
-using namespace mozilla::gfx;
-using namespace std;
-
-CompositorVsyncScheduler::Observer::Observer(CompositorVsyncScheduler* aOwner)
-  : mMutex("CompositorVsyncScheduler.Observer.Mutex")
-  , mOwner(aOwner)
-{
-}
-
-CompositorVsyncScheduler::Observer::~Observer()
-{
-  MOZ_ASSERT(!mOwner);
-}
-
-bool
-CompositorVsyncScheduler::Observer::NotifyVsync(TimeStamp aVsyncTimestamp)
-{
-  MutexAutoLock lock(mMutex);
-  if (!mOwner) {
-    return false;
-  }
-  return mOwner->NotifyVsync(aVsyncTimestamp);
-}
-
-void
-CompositorVsyncScheduler::Observer::Destroy()
-{
-  MutexAutoLock lock(mMutex);
-  mOwner = nullptr;
-}
-
-CompositorVsyncScheduler::CompositorVsyncScheduler(CompositorVsyncSchedulerOwner* aVsyncSchedulerOwner,
-                                                   widget::CompositorWidget* aWidget)
-  : mVsyncSchedulerOwner(aVsyncSchedulerOwner)
-  , mLastCompose(TimeStamp::Now())
-  , mIsObservingVsync(false)
-  , mNeedsComposite(0)
-  , mVsyncNotificationsSkipped(0)
-  , mWidget(aWidget)
-  , mCurrentCompositeTaskMonitor("CurrentCompositeTaskMonitor")
-  , mCurrentCompositeTask(nullptr)
-  , mSetNeedsCompositeMonitor("SetNeedsCompositeMonitor")
-  , mSetNeedsCompositeTask(nullptr)
-{
-  MOZ_ASSERT(NS_IsMainThread() || XRE_GetProcessType() == GeckoProcessType_GPU);
-  mVsyncObserver = new Observer(this);
-
-  // mAsapScheduling is set on the main thread during init,
-  // but is only accessed after on the compositor thread.
-  mAsapScheduling = gfxPrefs::LayersCompositionFrameRate() == 0 ||
-                    gfxPlatform::IsInLayoutAsapMode();
-}
-
-CompositorVsyncScheduler::~CompositorVsyncScheduler()
-{
-  MOZ_ASSERT(!mIsObservingVsync);
-  MOZ_ASSERT(!mVsyncObserver);
-  // The CompositorVsyncDispatcher is cleaned up before this in the nsBaseWidget, which stops vsync listeners
-  mVsyncSchedulerOwner = nullptr;
-}
-
-void
-CompositorVsyncScheduler::Destroy()
-{
-  if (!mVsyncObserver) {
-    // Destroy was already called on this object.
-    return;
-  }
-  MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
-  UnobserveVsync();
-  mVsyncObserver->Destroy();
-  mVsyncObserver = nullptr;
-
-  CancelCurrentSetNeedsCompositeTask();
-  CancelCurrentCompositeTask();
-}
-
-void
-CompositorVsyncScheduler::PostCompositeTask(TimeStamp aCompositeTimestamp)
-{
-  // can be called from the compositor or vsync thread
-  MonitorAutoLock lock(mCurrentCompositeTaskMonitor);
-  if (mCurrentCompositeTask == nullptr && CompositorThreadHolder::Loop()) {
-    RefPtr<CancelableRunnable> task =
-      NewCancelableRunnableMethod<TimeStamp>(this, &CompositorVsyncScheduler::Composite,
-                                             aCompositeTimestamp);
-    mCurrentCompositeTask = task;
-    ScheduleTask(task.forget(), 0);
-  }
-}
-
-void
-CompositorVsyncScheduler::ScheduleComposition()
-{
-  MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
-  if (mAsapScheduling) {
-    // Used only for performance testing purposes
-    PostCompositeTask(TimeStamp::Now());
-#ifdef MOZ_WIDGET_ANDROID
-  } else if (mNeedsComposite >= 2 && mIsObservingVsync) {
-    // uh-oh, we already requested a composite at least twice so far, and a
-    // composite hasn't happened yet. It is possible that the vsync observation
-    // is blocked on the main thread, so let's just composite ASAP and not
-    // wait for the vsync. Note that this should only ever happen on Fennec
-    // because there content runs in the same process as the compositor, and so
-    // content can actually block the main thread in this process.
-    PostCompositeTask(TimeStamp::Now());
-#endif
-  } else {
-    SetNeedsComposite();
-  }
-}
-
-void
-CompositorVsyncScheduler::CancelCurrentSetNeedsCompositeTask()
-{
-  MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
-  MonitorAutoLock lock(mSetNeedsCompositeMonitor);
-  if (mSetNeedsCompositeTask) {
-    mSetNeedsCompositeTask->Cancel();
-    mSetNeedsCompositeTask = nullptr;
-  }
-  mNeedsComposite = 0;
-}
-
-/**
- * TODO Potential performance heuristics:
- * If a composite takes 17 ms, do we composite ASAP or wait until next vsync?
- * If a layer transaction comes after vsync, do we composite ASAP or wait until
- * next vsync?
- * How many skipped vsync events until we stop listening to vsync events?
- */
-void
-CompositorVsyncScheduler::SetNeedsComposite()
-{
-  if (!CompositorThreadHolder::IsInCompositorThread()) {
-    MonitorAutoLock lock(mSetNeedsCompositeMonitor);
-    RefPtr<CancelableRunnable> task =
-      NewCancelableRunnableMethod(this, &CompositorVsyncScheduler::SetNeedsComposite);
-    mSetNeedsCompositeTask = task;
-    ScheduleTask(task.forget(), 0);
-    return;
-  } else {
-    MonitorAutoLock lock(mSetNeedsCompositeMonitor);
-    mSetNeedsCompositeTask = nullptr;
-  }
-
-  mNeedsComposite++;
-  if (!mIsObservingVsync && mNeedsComposite) {
-    ObserveVsync();
-  }
-}
-
-bool
-CompositorVsyncScheduler::NotifyVsync(TimeStamp aVsyncTimestamp)
-{
-  // Called from the vsync dispatch thread. When in the GPU Process, that's
-  // the same as the compositor thread.
-  MOZ_ASSERT_IF(XRE_IsParentProcess(), !CompositorThreadHolder::IsInCompositorThread());
-  MOZ_ASSERT_IF(XRE_GetProcessType() == GeckoProcessType_GPU, CompositorThreadHolder::IsInCompositorThread());
-  MOZ_ASSERT(!NS_IsMainThread());
-  PostCompositeTask(aVsyncTimestamp);
-  return true;
-}
-
-void
-CompositorVsyncScheduler::CancelCurrentCompositeTask()
-{
-  MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread() || NS_IsMainThread());
-  MonitorAutoLock lock(mCurrentCompositeTaskMonitor);
-  if (mCurrentCompositeTask) {
-    mCurrentCompositeTask->Cancel();
-    mCurrentCompositeTask = nullptr;
-  }
-}
-
-void
-CompositorVsyncScheduler::Composite(TimeStamp aVsyncTimestamp)
-{
-  MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
-  {
-    MonitorAutoLock lock(mCurrentCompositeTaskMonitor);
-    mCurrentCompositeTask = nullptr;
-  }
-
-  if ((aVsyncTimestamp < mLastCompose) && !mAsapScheduling) {
-    // We can sometimes get vsync timestamps that are in the past
-    // compared to the last compose with force composites.
-    // In those cases, wait until the next vsync;
-    return;
-  }
-
-  MOZ_ASSERT(mVsyncSchedulerOwner);
-  if (!mAsapScheduling && mVsyncSchedulerOwner->IsPendingComposite()) {
-    // If previous composite is still on going, finish it and does a next
-    // composite in a next vsync.
-    mVsyncSchedulerOwner->FinishPendingComposite();
-    return;
-  }
-
-  DispatchTouchEvents(aVsyncTimestamp);
-  DispatchVREvents(aVsyncTimestamp);
-
-  if (mNeedsComposite || mAsapScheduling) {
-    mNeedsComposite = 0;
-    mLastCompose = aVsyncTimestamp;
-    ComposeToTarget(nullptr);
-    mVsyncNotificationsSkipped = 0;
-
-    TimeDuration compositeFrameTotal = TimeStamp::Now() - aVsyncTimestamp;
-    mozilla::Telemetry::Accumulate(mozilla::Telemetry::COMPOSITE_FRAME_ROUNDTRIP_TIME,
-                                   compositeFrameTotal.ToMilliseconds());
-  } else if (mVsyncNotificationsSkipped++ > gfxPrefs::CompositorUnobserveCount()) {
-    UnobserveVsync();
-  }
-}
-
-void
-CompositorVsyncScheduler::OnForceComposeToTarget()
-{
-  /**
-   * bug 1138502 - There are cases such as during long-running window resizing events
-   * where we receive many sync RecvFlushComposites. We also get vsync notifications which
-   * will increment mVsyncNotificationsSkipped because a composite just occurred. After
-   * enough vsyncs and RecvFlushComposites occurred, we will disable vsync. Then at the next
-   * ScheduleComposite, we will enable vsync, then get a RecvFlushComposite, which will
-   * force us to unobserve vsync again. On some platforms, enabling/disabling vsync is not
-   * free and this oscillating behavior causes a performance hit. In order to avoid this problem,
-   * we reset the mVsyncNotificationsSkipped counter to keep vsync enabled.
-   */
-  MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
-  mVsyncNotificationsSkipped = 0;
-}
-
-void
-CompositorVsyncScheduler::ForceComposeToTarget(gfx::DrawTarget* aTarget, const IntRect* aRect)
-{
-  MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
-  OnForceComposeToTarget();
-  mLastCompose = TimeStamp::Now();
-  ComposeToTarget(aTarget, aRect);
-}
-
-bool
-CompositorVsyncScheduler::NeedsComposite()
-{
-  MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
-  return mNeedsComposite;
-}
-
-void
-CompositorVsyncScheduler::ObserveVsync()
-{
-  MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
-  mWidget->ObserveVsync(mVsyncObserver);
-  mIsObservingVsync = true;
-}
-
-void
-CompositorVsyncScheduler::UnobserveVsync()
-{
-  MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
-  mWidget->ObserveVsync(nullptr);
-  mIsObservingVsync = false;
-}
-
-void
-CompositorVsyncScheduler::DispatchTouchEvents(TimeStamp aVsyncTimestamp)
-{
-}
-
-void
-CompositorVsyncScheduler::DispatchVREvents(TimeStamp aVsyncTimestamp)
-{
-  MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
-
-  VRManager* vm = VRManager::Get();
-  vm->NotifyVsync(aVsyncTimestamp);
-}
-
-void
-CompositorVsyncScheduler::ScheduleTask(already_AddRefed<CancelableRunnable> aTask,
-                                       int aTime)
-{
-  MOZ_ASSERT(CompositorThreadHolder::Loop());
-  MOZ_ASSERT(aTime >= 0);
-  CompositorThreadHolder::Loop()->PostDelayedTask(Move(aTask), aTime);
-}
-
-void
-CompositorVsyncScheduler::ResumeComposition()
-{
-  MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
-  mLastCompose = TimeStamp::Now();
-  ComposeToTarget(nullptr);
-}
-
-void
-CompositorVsyncScheduler::ComposeToTarget(gfx::DrawTarget* aTarget, const IntRect* aRect)
-{
-  MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
-  MOZ_ASSERT(mVsyncSchedulerOwner);
-  mVsyncSchedulerOwner->CompositeToTarget(aTarget, aRect);
-}
-
-} // namespace layers
-} // namespace mozilla
deleted file mode 100644
--- a/gfx/layers/ipc/CompositorVsyncScheduler.h
+++ /dev/null
@@ -1,131 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set sw=4 ts=8 et tw=80 : */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_layers_CompositorVsyncScheduler_h
-#define mozilla_layers_CompositorVsyncScheduler_h
-
-#include <stdint.h>                     // for uint64_t
-
-#include "mozilla/Attributes.h"         // for override
-#include "mozilla/Monitor.h"            // for Monitor
-#include "mozilla/RefPtr.h"             // for RefPtr
-#include "mozilla/TimeStamp.h"          // for TimeStamp
-#include "mozilla/gfx/Point.h"          // for IntSize
-#include "mozilla/VsyncDispatcher.h"
-#include "mozilla/widget/CompositorWidget.h"
-#include "nsISupportsImpl.h"
-
-
-class MessageLoop;
-class nsIWidget;
-
-namespace mozilla {
-
-class CancelableRunnable;
-
-namespace gfx {
-class DrawTarget;
-} // namespace gfx
-
-namespace layers {
-
-class CompositorVsyncSchedulerOwner
-{
-public:
-  virtual bool IsPendingComposite() = 0;
-  virtual void FinishPendingComposite() = 0;
-  virtual void CompositeToTarget(gfx::DrawTarget* aTarget, const gfx::IntRect* aRect = nullptr) = 0;
-};
-
-/**
- * Manages the vsync (de)registration and tracking on behalf of the
- * compositor when it need to paint.
- * Turns vsync notifications into scheduled composites.
- **/
-class CompositorVsyncScheduler
-{
-  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CompositorVsyncScheduler)
-
-public:
-  explicit CompositorVsyncScheduler(CompositorVsyncSchedulerOwner* aVsyncSchedulerOwner,
-                                    widget::CompositorWidget* aWidget);
-
-  bool NotifyVsync(TimeStamp aVsyncTimestamp);
-  void SetNeedsComposite();
-  void OnForceComposeToTarget();
-
-  void ScheduleTask(already_AddRefed<CancelableRunnable>, int);
-  void ResumeComposition();
-  void ComposeToTarget(gfx::DrawTarget* aTarget, const gfx::IntRect* aRect = nullptr);
-  void PostCompositeTask(TimeStamp aCompositeTimestamp);
-  void Destroy();
-  void ScheduleComposition();
-  void CancelCurrentCompositeTask();
-  bool NeedsComposite();
-  void Composite(TimeStamp aVsyncTimestamp);
-  void ForceComposeToTarget(gfx::DrawTarget* aTarget, const gfx::IntRect* aRect);
-
-  const TimeStamp& GetLastComposeTime()
-  {
-    return mLastCompose;
-  }
-
-#ifdef COMPOSITOR_PERFORMANCE_WARNING
-  const TimeStamp& GetExpectedComposeStartTime()
-  {
-    return mExpectedComposeStartTime;
-  }
-#endif
-
-private:
-  virtual ~CompositorVsyncScheduler();
-
-  void NotifyCompositeTaskExecuted();
-  void ObserveVsync();
-  void UnobserveVsync();
-  void DispatchTouchEvents(TimeStamp aVsyncTimestamp);
-  void DispatchVREvents(TimeStamp aVsyncTimestamp);
-  void CancelCurrentSetNeedsCompositeTask();
-
-  class Observer final : public VsyncObserver
-  {
-  public:
-    explicit Observer(CompositorVsyncScheduler* aOwner);
-    virtual bool NotifyVsync(TimeStamp aVsyncTimestamp) override;
-    void Destroy();
-  private:
-    virtual ~Observer();
-
-    Mutex mMutex;
-    // Hold raw pointer to avoid mutual reference.
-    CompositorVsyncScheduler* mOwner;
-  };
-
-  CompositorVsyncSchedulerOwner* mVsyncSchedulerOwner;
-  TimeStamp mLastCompose;
-
-#ifdef COMPOSITOR_PERFORMANCE_WARNING
-  TimeStamp mExpectedComposeStartTime;
-#endif
-
-  bool mAsapScheduling;
-  bool mIsObservingVsync;
-  uint32_t mNeedsComposite;
-  int32_t mVsyncNotificationsSkipped;
-  widget::CompositorWidget* mWidget;
-  RefPtr<CompositorVsyncScheduler::Observer> mVsyncObserver;
-
-  mozilla::Monitor mCurrentCompositeTaskMonitor;
-  RefPtr<CancelableRunnable> mCurrentCompositeTask;
-
-  mozilla::Monitor mSetNeedsCompositeMonitor;
-  RefPtr<CancelableRunnable> mSetNeedsCompositeTask;
-};
-
-} // namespace layers
-} // namespace mozilla
-
-#endif // mozilla_layers_CompositorVsyncScheduler_h
--- a/gfx/layers/ipc/CrossProcessCompositorBridgeParent.cpp
+++ b/gfx/layers/ipc/CrossProcessCompositorBridgeParent.cpp
@@ -264,17 +264,17 @@ CrossProcessCompositorBridgeParent::Allo
 
   MonitorAutoLock lock(*sIndirectLayerTreesLock);
   MOZ_ASSERT(sIndirectLayerTrees.find(aPipelineId) != sIndirectLayerTrees.end());
   MOZ_ASSERT(sIndirectLayerTrees[aPipelineId].mWRBridge == nullptr);
   CompositorBridgeParent* cbp = sIndirectLayerTrees[aPipelineId].mParent;
   WebRenderBridgeParent* root = sIndirectLayerTrees[cbp->RootLayerTreeId()].mWRBridge.get();
 
   WebRenderBridgeParent* parent = new WebRenderBridgeParent(
-    root, aPipelineId, nullptr, nullptr, root->GLContext(), root->WindowState(), root->Compositor());
+    aPipelineId, nullptr, nullptr, root->GLContext(), root->WindowState(), root->Compositor());
   parent->AddRef(); // IPDL reference
   sIndirectLayerTrees[aPipelineId].mWRBridge = parent;
 
   return parent;
 }
 
 bool
 CrossProcessCompositorBridgeParent::DeallocPWebRenderBridgeParent(PWebRenderBridgeParent* aActor)
--- a/gfx/layers/moz.build
+++ b/gfx/layers/moz.build
@@ -163,17 +163,16 @@ EXPORTS.mozilla.layers += [
     'ipc/APZChild.h',
     'ipc/APZCTreeManagerChild.h',
     'ipc/APZCTreeManagerParent.h',
     'ipc/CompositableForwarder.h',
     'ipc/CompositableTransactionParent.h',
     'ipc/CompositorBridgeChild.h',
     'ipc/CompositorBridgeParent.h',
     'ipc/CompositorThread.h',
-    'ipc/CompositorVsyncScheduler.h',
     'ipc/CrossProcessCompositorBridgeParent.h',
     'ipc/ImageBridgeChild.h',
     'ipc/ImageBridgeParent.h',
     'ipc/ImageContainerChild.h',
     'ipc/ImageContainerParent.h',
     'ipc/ISurfaceAllocator.h',
     'ipc/KnowsCompositor.h',
     'ipc/LayerAnimationUtils.h',
@@ -337,17 +336,16 @@ UNIFIED_SOURCES += [
     'ipc/APZCTreeManagerChild.cpp',
     'ipc/APZCTreeManagerParent.cpp',
     'ipc/CompositableForwarder.cpp',
     'ipc/CompositableTransactionParent.cpp',
     'ipc/CompositorBench.cpp',
     'ipc/CompositorBridgeChild.cpp',
     'ipc/CompositorBridgeParent.cpp',
     'ipc/CompositorThread.cpp',
-    'ipc/CompositorVsyncScheduler.cpp',
     'ipc/CrossProcessCompositorBridgeParent.cpp',
     'ipc/ImageBridgeChild.cpp',
     'ipc/ImageBridgeParent.cpp',
     'ipc/ImageContainerChild.cpp',
     'ipc/ImageContainerParent.cpp',
     'ipc/ISurfaceAllocator.cpp',
     'ipc/LayerAnimationUtils.cpp',
     'ipc/LayerTransactionChild.cpp',
--- a/gfx/layers/wr/WebRenderBridgeParent.cpp
+++ b/gfx/layers/wr/WebRenderBridgeParent.cpp
@@ -9,25 +9,23 @@
 #include "GLContext.h"
 #include "GLContextProvider.h"
 #include "mozilla/layers/Compositor.h"
 #include "mozilla/widget/CompositorWidget.h"
 
 namespace mozilla {
 namespace layers {
 
-WebRenderBridgeParent::WebRenderBridgeParent(WebRenderBridgeParent* aParent,
-                                             const uint64_t& aPipelineId,
+WebRenderBridgeParent::WebRenderBridgeParent(const uint64_t& aPipelineId,
                                              const nsString* aResourcePath,
                                              widget::CompositorWidget* aWidget,
                                              gl::GLContext* aGlContext,
                                              wrwindowstate* aWrWindowState,
                                              layers::Compositor* aCompositor)
-  : mParent(aParent)
-  , mPipelineId(aPipelineId)
+  : mPipelineId(aPipelineId)
   , mWidget(aWidget)
   , mWRState(nullptr)
   , mGLContext(aGlContext)
   , mWRWindowState(aWrWindowState)
   , mCompositor(aCompositor)
 {
   MOZ_ASSERT(mGLContext);
   MOZ_ASSERT(mCompositor);
@@ -35,19 +33,16 @@ WebRenderBridgeParent::WebRenderBridgePa
     // mWRWindowState should only be null for the root WRBP of a layers tree,
     // i.e. the one created by the CompositorBridgeParent as opposed to the
     // CrossProcessCompositorBridgeParent
     MOZ_ASSERT(mWidget);
     MOZ_ASSERT(aResourcePath);
     mWRWindowState = wr_init_window(mPipelineId,
                                     NS_ConvertUTF16toUTF8(*aResourcePath).get());
   }
-  if (mWidget) {
-    mCompositorScheduler = new CompositorVsyncScheduler(this, mWidget);
-  }
 }
 
 mozilla::ipc::IPCResult
 WebRenderBridgeParent::RecvCreate(const uint32_t& aWidth,
                                   const uint32_t& aHeight)
 {
   if (mWRState) {
     return IPC_OK();
@@ -65,21 +60,16 @@ WebRenderBridgeParent::RecvDestroy()
   MOZ_ASSERT(mCompositor);
   wr_destroy(mWRState);
   mWRState = nullptr;
   if (mWidget) {
     // Only the "root" WebRenderBridgeParent (the one with the widget ptr) owns
     // the compositor ref and needs to destroy it.
     mCompositor->Destroy();
   }
-  if (mCompositorScheduler) {
-    mCompositorScheduler->Destroy();
-    mCompositorScheduler = nullptr;
-  }
-  mParent = nullptr;
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
 WebRenderBridgeParent::RecvAddImage(const uint32_t& aWidth,
                                     const uint32_t& aHeight,
                                     const uint32_t& aStride,
                                     const WRImageFormat& aFormat,
@@ -114,16 +104,27 @@ WebRenderBridgeParent::RecvDeleteImage(c
 }
 
 mozilla::ipc::IPCResult
 WebRenderBridgeParent::RecvDPBegin(const uint32_t& aWidth,
                                    const uint32_t& aHeight,
                                    bool* aOutSuccess)
 {
   MOZ_ASSERT(mWRState);
+  if (mWidget) {
+    mozilla::widget::WidgetRenderingContext widgetContext;
+#if defined(XP_MACOSX)
+    widgetContext.mGL = mGLContext;
+#endif
+    if (!mWidget->PreRender(&widgetContext)) {
+      *aOutSuccess = false;
+      return IPC_OK();
+    }
+  }
+  mGLContext->MakeCurrent();
   wr_dp_begin(mWRWindowState, mWRState, aWidth, aHeight);
   *aOutSuccess = true;
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
 WebRenderBridgeParent::RecvDPEnd(InfallibleTArray<WebRenderCommand>&& commands)
 {
@@ -155,66 +156,38 @@ WebRenderBridgeParent::RecvDPEnd(Infalli
         const OpDPPushIframe& op = cmd.get_OpDPPushIframe();
         wr_dp_push_iframe(mWRState, op.bounds(), op.clip(), op.layersid());
         break;
       }
       default:
         NS_RUNTIMEABORT("not reached");
     }
   }
+  mGLContext->MakeCurrent();
   wr_dp_end(mWRWindowState, mWRState);
-  ScheduleComposition();
-  DeleteOldImages();
-  return IPC_OK();
-}
-
-void
-WebRenderBridgeParent::CompositeToTarget(gfx::DrawTarget* aTarget, const gfx::IntRect* aRect)
-{
-  if (aTarget) {
-    // XXX Add compositing to DrawTarget
-    return;
-  }
-  if (!mWidget) {
-    return;
-  }
-
-  MOZ_ASSERT(mWRState);
-  {
+  mGLContext->SwapBuffers();
+  if (mWidget) {
     mozilla::widget::WidgetRenderingContext widgetContext;
 #if defined(XP_MACOSX)
     widgetContext.mGL = mGLContext;
 #endif
-    if (!mWidget->PreRender(&widgetContext)) {
-      return;
-    }
+    mWidget->PostRender(&widgetContext);
   }
 
-  mGLContext->MakeCurrent();
-  wr_composite(mWRWindowState);
-  mGLContext->SwapBuffers();
+  DeleteOldImages();
+  return IPC_OK();
 }
 
 WebRenderBridgeParent::~WebRenderBridgeParent()
 {
 }
 
 void
 WebRenderBridgeParent::DeleteOldImages()
 {
   for (WRImageKey key : mKeysToDelete) {
     wr_delete_image(mWRWindowState, key);
   }
   mKeysToDelete.clear();
 }
 
-void
-WebRenderBridgeParent::ScheduleComposition()
-{
-  if (mWidget) {
-    mCompositorScheduler->ScheduleComposition();
-  } else {
-    mParent->ScheduleComposition();
-  }
-}
-
 } // namespace layers
 } // namespace mozilla
--- a/gfx/layers/wr/WebRenderBridgeParent.h
+++ b/gfx/layers/wr/WebRenderBridgeParent.h
@@ -3,17 +3,16 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_layers_WebRenderBridgeParent_h
 #define mozilla_layers_WebRenderBridgeParent_h
 
 #include "GLContextProvider.h"
-#include "mozilla/layers/CompositorVsyncScheduler.h"
 #include "mozilla/layers/PWebRenderBridgeParent.h"
 #include "mozilla/layers/WebRenderTypes.h"
 
 namespace mozilla {
 
 namespace gl {
 class GLContext;
 }
@@ -22,23 +21,21 @@ namespace widget {
 class CompositorWidget;
 }
 
 namespace layers {
 
 class Compositor;
 
 class WebRenderBridgeParent final : public PWebRenderBridgeParent
-                                  , public CompositorVsyncSchedulerOwner
 {
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WebRenderBridgeParent)
 
 public:
-  WebRenderBridgeParent(WebRenderBridgeParent* aParent,
-                        const uint64_t& aPipelineId,
+  WebRenderBridgeParent(const uint64_t& aPipelineId,
                         const nsString* aResourcePath,
                         widget::CompositorWidget* aWidget,
                         gl::GLContext* aGlContext,
                         wrwindowstate* aWrWindowState,
                         layers::Compositor* aCompositor);
   uint64_t PipelineId() { return mPipelineId; }
   gl::GLContext* GLContext() { return mGLContext.get(); }
   wrwindowstate* WindowState() { return mWRWindowState; }
@@ -61,34 +58,26 @@ public:
   mozilla::ipc::IPCResult RecvDeleteImage(const WRImageKey& aImageKey) override;
   mozilla::ipc::IPCResult RecvDPBegin(const uint32_t& aWidth,
                                       const uint32_t& aHeight,
                                       bool* aOutSuccess) override;
   mozilla::ipc::IPCResult RecvDPEnd(InfallibleTArray<WebRenderCommand>&& commands) override;
 
   void ActorDestroy(ActorDestroyReason aWhy) override {}
 
-  // CompositorVsyncSchedulerOwner
-  bool IsPendingComposite() override { return false; }
-  void FinishPendingComposite() override { }
-  void CompositeToTarget(gfx::DrawTarget* aTarget, const gfx::IntRect* aRect = nullptr) override;
-
 protected:
   virtual ~WebRenderBridgeParent();
   void DeleteOldImages();
-  void ScheduleComposition();
+
 private:
-  // XXX remove mParent in Bug 1317935
-  RefPtr<WebRenderBridgeParent> mParent;
   uint64_t mPipelineId;
   RefPtr<widget::CompositorWidget> mWidget;
   wrstate* mWRState;
   RefPtr<gl::GLContext> mGLContext;
   wrwindowstate* mWRWindowState;
   RefPtr<layers::Compositor> mCompositor;
-  RefPtr<CompositorVsyncScheduler> mCompositorScheduler;
   std::vector<WRImageKey> mKeysToDelete;
 };
 
 } // namespace layers
 } // namespace mozilla
 
 #endif // mozilla_layers_WebRenderBridgeParent_h
--- a/gfx/webrender/src/bindings.rs
+++ b/gfx/webrender/src/bindings.rs
@@ -370,23 +370,27 @@ pub extern fn wr_dp_end(window: &mut WrW
 
     window.api.set_root_display_list(root_background_color,
                                      epoch,
                                      pipeline_id,
                                      Size2D::new(width as f32, height as f32),
                                      fb.root_dl_builder.finalize(),
                                      fb.auxiliary_lists_builder.finalize()
                                      );
+
+    gl::clear(gl::COLOR_BUFFER_BIT);
+    window.renderer.update();
+
+    window.renderer.render(window.size);
 }
 
 #[no_mangle]
 pub extern fn wr_composite(window: &mut WrWindowState) {
     window.api.generate_frame();
 
-    gl::clear(gl::COLOR_BUFFER_BIT);
     window.renderer.update();
     window.renderer.render(window.size);
 }
 
 #[no_mangle]
 pub extern fn wr_add_image(window: &mut WrWindowState, width: u32, height: u32, stride: u32, format: ImageFormat, bytes: * const u8, size: usize) -> ImageKey {
     let bytes = unsafe { slice::from_raw_parts(bytes, size).to_owned() };
     let stride_option = match stride {