Bug 1184283 - have compositor listen to its Widget for vsync draft
authorVladimir Vukicevic <vladimir@pobox.com>
Mon, 25 Jan 2016 17:09:53 -0500
changeset 356574 980ebb2a8e3bd9bbb657ffbc310f2875eabe0bba
parent 356573 9f4c88a76d8f1b573eb2d99739d2a5ed4e0aaa92
child 356575 771fcb2d5baa92821f97715055680b3558bca660
push id16548
push userbmo:vladimir@pobox.com
push dateTue, 26 Apr 2016 17:19:15 +0000
bugs1184283
milestone49.0a1
Bug 1184283 - have compositor listen to its Widget for vsync
gfx/layers/ipc/CompositorBridgeParent.cpp
gfx/layers/ipc/CompositorBridgeParent.h
--- a/gfx/layers/ipc/CompositorBridgeParent.cpp
+++ b/gfx/layers/ipc/CompositorBridgeParent.cpp
@@ -70,17 +70,19 @@
 #include "mozilla/ipc/GeckoChildProcessHost.h"
 #include "mozilla/unused.h"
 #include "mozilla/Hal.h"
 #include "mozilla/HalTypes.h"
 #include "mozilla/StaticPtr.h"
 #ifdef MOZ_ENABLE_PROFILER_SPS
 #include "ProfilerMarkers.h"
 #endif
-#include "mozilla/VsyncDispatcher.h"
+
+extern PRLogModuleInfo *gVsyncLog;
+#define VSYNC_LOG(...)  MOZ_LOG(gVsyncLog, mozilla::LogLevel::Debug, (__VA_ARGS__))
 
 #ifdef MOZ_WIDGET_GONK
 #include "GeckoTouchDispatcher.h"
 #include "nsScreenManagerGonk.h"
 #endif
 
 #ifdef MOZ_ANDROID_APZ
 #include "AndroidBridge.h"
@@ -284,24 +286,23 @@ CompositorVsyncScheduler::Observer::Obse
 {
 }
 
 CompositorVsyncScheduler::Observer::~Observer()
 {
   MOZ_ASSERT(!mOwner);
 }
 
-bool
+void
 CompositorVsyncScheduler::Observer::NotifyVsync(TimeStamp aVsyncTimestamp)
 {
   MutexAutoLock lock(mMutex);
-  if (!mOwner) {
-    return false;
+  if (mOwner) {
+    mOwner->NotifyVsync(aVsyncTimestamp);
   }
-  return mOwner->NotifyVsync(aVsyncTimestamp);
 }
 
 void
 CompositorVsyncScheduler::Observer::Destroy()
 {
   MutexAutoLock lock(mMutex);
   mOwner = nullptr;
 }
@@ -322,17 +323,16 @@ CompositorVsyncScheduler::CompositorVsyn
   , mSetDisplayMonitor("SetDisplayMonitor")
   , mSetDisplayTask(nullptr)
 #endif
 #endif
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(aWidget != nullptr);
   mVsyncObserver = new Observer(this);
-  mCompositorVsyncDispatcher = aWidget->GetCompositorVsyncDispatcher();
 #ifdef MOZ_WIDGET_GONK
   GeckoTouchDispatcher::GetInstance()->SetCompositorVsyncScheduler(this);
 
 #if ANDROID_VERSION >= 19
   RefPtr<nsScreenManagerGonk> screenManager = nsScreenManagerGonk::GetInstance();
   screenManager->SetCompositorVsyncScheduler(this);
 #endif
 #endif
@@ -342,19 +342,17 @@ CompositorVsyncScheduler::CompositorVsyn
   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;
-  mCompositorVsyncDispatcher = nullptr;
 }
 
 #ifdef MOZ_WIDGET_GONK
 #if ANDROID_VERSION >= 19
 void
 CompositorVsyncScheduler::SetDisplay(bool aDisplayEnable)
 {
   // SetDisplay() is usually called from nsScreenManager at main thread. Post
@@ -398,22 +396,27 @@ CompositorVsyncScheduler::CancelSetDispl
   mDisplayEnabled = false;
 }
 #endif //ANDROID_VERSION >= 19
 #endif //MOZ_WIDGET_GONK
 
 void
 CompositorVsyncScheduler::Destroy()
 {
+  MOZ_ASSERT(CompositorBridgeParent::IsInCompositorThread());
+
+  VSYNC_LOG("VsyncScheduler %p Destroy\n", this);
+
   if (!mVsyncObserver) {
     // Destroy was already called on this object.
     return;
   }
-  MOZ_ASSERT(CompositorBridgeParent::IsInCompositorThread());
+
   UnobserveVsync();
+
   mVsyncObserver->Destroy();
   mVsyncObserver = nullptr;
 
 #ifdef MOZ_WIDGET_GONK
 #if ANDROID_VERSION >= 19
   CancelSetDisplayTask();
 #endif
 #endif
@@ -589,26 +592,30 @@ CompositorVsyncScheduler::NeedsComposite
 {
   MOZ_ASSERT(CompositorBridgeParent::IsInCompositorThread());
   return mNeedsComposite;
 }
 
 void
 CompositorVsyncScheduler::ObserveVsync()
 {
-  MOZ_ASSERT(CompositorBridgeParent::IsInCompositorThread());
-  mCompositorVsyncDispatcher->SetCompositorVsyncObserver(mVsyncObserver);
+  MOZ_ASSERT(mCompositorBridgeParent);
+  MOZ_ASSERT(mCompositorBridgeParent->GetWidget());
+  mCompositorBridgeParent->GetWidget()->AddVsyncObserver(mVsyncObserver);
   mIsObservingVsync = true;
 }
 
 void
 CompositorVsyncScheduler::UnobserveVsync()
 {
-  MOZ_ASSERT(CompositorBridgeParent::IsInCompositorThread());
-  mCompositorVsyncDispatcher->SetCompositorVsyncObserver(nullptr);
+  // if we're being called from Destroy, the connection may have been
+  // already destroyed
+  if (mCompositorBridgeParent->GetWidget()) {
+    mCompositorBridgeParent->GetWidget()->RemoveVsyncObserver(mVsyncObserver);
+  }
   mIsObservingVsync = false;
 }
 
 void
 CompositorVsyncScheduler::DispatchTouchEvents(TimeStamp aVsyncTimestamp)
 {
 #ifdef MOZ_WIDGET_GONK
   GeckoTouchDispatcher::GetInstance()->NotifyVsync(aVsyncTimestamp);
@@ -777,22 +784,30 @@ CompositorBridgeParent::RecvWillClose()
       lts->mLayerManager = nullptr;
       lts->mParent = nullptr;
     });
     mLayerManager->Destroy();
     mLayerManager = nullptr;
     mCompositionManager = nullptr;
   }
 
+  if (mCompositorScheduler) {
+    mCompositorScheduler->Destroy();
+  }
+
   if (mCompositor) {
     mCompositor->DetachWidget();
     mCompositor->Destroy();
     mCompositor = nullptr;
   }
 
+  // we shouldn't try to access the widget any more, since it'll go
+  // away shortly
+  mWidget = nullptr;
+  
   return true;
 }
 
 void CompositorBridgeParent::DeferredDestroy()
 {
   MOZ_ASSERT(!NS_IsMainThread());
   MOZ_ASSERT(mCompositorThreadHolder);
   mCompositorThreadHolder = nullptr;
@@ -937,16 +952,21 @@ CompositorBridgeParent::UpdateVisibleReg
     // We need to recomposite to update the minimap.
     ScheduleComposition();
   }
 }
 
 void
 CompositorBridgeParent::ActorDestroy(ActorDestroyReason why)
 {
+  // at this point, we're going to assume our widget is unreachable --
+  // our scheduler cleanup (that needs the widget to unobserve) was done
+  // in WillClose
+  mWidget = nullptr;
+
   CancelCurrentCompositeTask();
   if (mForceCompositionTask) {
     mForceCompositionTask->Cancel();
     mForceCompositionTask = nullptr;
   }
   mPaused = true;
   RemoveCompositor(mCompositorID);
 
@@ -967,17 +987,20 @@ CompositorBridgeParent::ActorDestroy(Act
 
   mCompositionManager = nullptr;
 
   if (mApzcTreeManager) {
     mApzcTreeManager->ClearTree();
     mApzcTreeManager = nullptr;
   }
 
-  mCompositorScheduler->Destroy();
+  if (mCompositorScheduler) {
+    mCompositorScheduler->Destroy();
+    mCompositorScheduler = nullptr;
+  }
 
   // There are chances that the ref count reaches zero on the main thread shortly
   // after this function returns while some ipdl code still needs to run on
   // this thread.
   // We must keep the compositor parent alive untill the code handling message
   // reception is finished on this thread.
   mSelfRef = this;
   MessageLoop::current()->PostTask(FROM_HERE,
--- a/gfx/layers/ipc/CompositorBridgeParent.h
+++ b/gfx/layers/ipc/CompositorBridgeParent.h
@@ -32,17 +32,17 @@
 #include "mozilla/layers/GeckoContentController.h"
 #include "mozilla/layers/LayersMessages.h"  // for TargetConfig
 #include "mozilla/layers/PCompositorBridgeParent.h"
 #include "mozilla/layers/ShadowLayersManager.h" // for ShadowLayersManager
 #include "mozilla/layers/APZTestData.h"
 #include "nsAutoPtr.h"                  // for nsRefPtr
 #include "nsISupportsImpl.h"
 #include "ThreadSafeRefcountingWithMainThreadDestruction.h"
-#include "mozilla/VsyncDispatcher.h"
+#include "gfxVsync.h"
 
 class CancelableTask;
 class MessageLoop;
 class nsIWidget;
 
 namespace mozilla {
 namespace gfx {
 class DrawTarget;
@@ -159,21 +159,23 @@ private:
   void DispatchVREvents(TimeStamp aVsyncTimestamp);
   void CancelCurrentSetNeedsCompositeTask();
 #ifdef MOZ_WIDGET_GONK
 #if ANDROID_VERSION >= 19
   void CancelSetDisplayTask();
 #endif
 #endif
 
-  class Observer final : public VsyncObserver
+  class Observer final : public gfx::VsyncObserver
   {
+    NS_INLINE_DECL_THREADSAFE_REFCOUNTING(Observer, override)
+
   public:
     explicit Observer(CompositorVsyncScheduler* aOwner);
-    virtual bool NotifyVsync(TimeStamp aVsyncTimestamp) override;
+    virtual void NotifyVsync(TimeStamp aVsyncTimestamp) override;
     void Destroy();
   private:
     virtual ~Observer();
 
     Mutex mMutex;
     // Hold raw pointer to avoid mutual reference.
     CompositorVsyncScheduler* mOwner;
   };
@@ -184,17 +186,16 @@ private:
 #ifdef COMPOSITOR_PERFORMANCE_WARNING
   TimeStamp mExpectedComposeStartTime;
 #endif
 
   bool mAsapScheduling;
   bool mIsObservingVsync;
   uint32_t mNeedsComposite;
   int32_t mVsyncNotificationsSkipped;
-  RefPtr<CompositorVsyncDispatcher> mCompositorVsyncDispatcher;
   RefPtr<CompositorVsyncScheduler::Observer> mVsyncObserver;
 
   mozilla::Monitor mCurrentCompositeTaskMonitor;
   CancelableTask* mCurrentCompositeTask;
 
   mozilla::Monitor mSetNeedsCompositeMonitor;
   CancelableTask* mSetNeedsCompositeTask;