Bug 1408421 - Improving throttling GenerateFrame() r=jrmuizel
authorsotaro <sotaro.ikeda.g@gmail.com>
Fri, 03 Nov 2017 11:22:28 +0900
changeset 389966 14a5ae97c682ed92861492a1e51f041b6d6cef40
parent 389965 e255f93c08085eb8a4034d320c6af48827619908
child 389967 4e6df5159df3e64c3c453c0db0a2e1d126819b71
child 390134 943f22d90aca3ac389b97c9ac3b19452ec130f4a
push id32803
push usernbeleuzu@mozilla.com
push dateFri, 03 Nov 2017 10:05:35 +0000
treeherdermozilla-central@4e6df5159df3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjrmuizel
bugs1408421
milestone58.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
Bug 1408421 - Improving throttling GenerateFrame() r=jrmuizel
gfx/layers/wr/WebRenderBridgeParent.cpp
gfx/webrender_bindings/RenderThread.cpp
gfx/webrender_bindings/RenderThread.h
--- a/gfx/layers/wr/WebRenderBridgeParent.cpp
+++ b/gfx/layers/wr/WebRenderBridgeParent.cpp
@@ -1136,20 +1136,18 @@ WebRenderBridgeParent::SampleAnimations(
 void
 WebRenderBridgeParent::CompositeToTarget(gfx::DrawTarget* aTarget, const gfx::IntRect* aRect)
 {
   AUTO_PROFILER_TRACING("Paint", "CompositeToTraget");
   if (mPaused) {
     return;
   }
 
-  const uint32_t maxPendingFrameCount = 1;
-
   if (!mForceRendering &&
-      wr::RenderThread::Get()->GetPendingFrameCount(mApi->GetId()) >= maxPendingFrameCount) {
+      wr::RenderThread::Get()->TooManyPendingFrames(mApi->GetId())) {
     // Render thread is busy, try next time.
     ScheduleComposition();
     return;
   }
 
   bool scheduleComposite = false;
   nsTArray<wr::WrOpacityProperty> opacityArray;
   nsTArray<wr::WrTransformProperty> transformArray;
--- a/gfx/webrender_bindings/RenderThread.cpp
+++ b/gfx/webrender_bindings/RenderThread.cpp
@@ -18,17 +18,17 @@
 
 namespace mozilla {
 namespace wr {
 
 static StaticRefPtr<RenderThread> sRenderThread;
 
 RenderThread::RenderThread(base::Thread* aThread)
   : mThread(aThread)
-  , mPendingFrameCountMapLock("RenderThread.mPendingFrameCountMapLock")
+  , mFrameCountMapLock("RenderThread.mFrameCountMapLock")
   , mRenderTextureMapLock("RenderThread.mRenderTextureMapLock")
   , mHasShutdown(false)
 {
 
 }
 
 RenderThread::~RenderThread()
 {
@@ -112,32 +112,32 @@ RenderThread::AddRenderer(wr::WindowId a
   MOZ_ASSERT(IsInRenderThread());
 
   if (mHasShutdown) {
     return;
   }
 
   mRenderers[aWindowId] = Move(aRenderer);
 
-  MutexAutoLock lock(mPendingFrameCountMapLock);
-  mPendingFrameCounts.Put(AsUint64(aWindowId), 0);
+  MutexAutoLock lock(mFrameCountMapLock);
+  mPendingFrameCounts.Put(AsUint64(aWindowId), FrameCount());
 }
 
 void
 RenderThread::RemoveRenderer(wr::WindowId aWindowId)
 {
   MOZ_ASSERT(IsInRenderThread());
 
   if (mHasShutdown) {
     return;
   }
 
   mRenderers.erase(aWindowId);
 
-  MutexAutoLock lock(mPendingFrameCountMapLock);
+  MutexAutoLock lock(mFrameCountMapLock);
   mPendingFrameCounts.Remove(AsUint64(aWindowId));
 }
 
 RendererOGL*
 RenderThread::GetRenderer(wr::WindowId aWindowId)
 {
   MOZ_ASSERT(IsInRenderThread());
 
@@ -260,56 +260,87 @@ RenderThread::Resume(wr::WindowId aWindo
   MOZ_ASSERT(it != mRenderers.end());
   if (it == mRenderers.end()) {
     return false;
   }
   auto& renderer = it->second;
   return renderer->Resume();
 }
 
-uint32_t
-RenderThread::GetPendingFrameCount(wr::WindowId aWindowId)
+bool
+RenderThread::TooManyPendingFrames(wr::WindowId aWindowId)
 {
-  MutexAutoLock lock(mPendingFrameCountMapLock);
-  uint32_t count = 0;
-  MOZ_ASSERT(mPendingFrameCounts.Get(AsUint64(aWindowId), &count));
-  mPendingFrameCounts.Get(AsUint64(aWindowId), &count);
-  return count;
+  const int64_t maxFrameCount = 1;
+
+  // Too many pending frames if pending frames exit more than maxFrameCount
+  // or if RenderBackend is still processing a frame.
+
+  MutexAutoLock lock(mFrameCountMapLock);
+  FrameCount count;
+  if (!mPendingFrameCounts.Get(AsUint64(aWindowId), &count)) {
+    MOZ_ASSERT(false);
+    return true;
+  }
+
+  if (count.mPendingCount > maxFrameCount) {
+    return true;
+  }
+  MOZ_ASSERT(count.mPendingCount >= count.mRenderingCount);
+  return count.mPendingCount > count.mRenderingCount;
 }
 
 void
 RenderThread::IncPendingFrameCount(wr::WindowId aWindowId)
 {
-  MutexAutoLock lock(mPendingFrameCountMapLock);
+  MutexAutoLock lock(mFrameCountMapLock);
   // Get the old count.
-  uint32_t oldCount = 0;
-  if (!mPendingFrameCounts.Get(AsUint64(aWindowId), &oldCount)) {
+  FrameCount count;
+  if (!mPendingFrameCounts.Get(AsUint64(aWindowId), &count)) {
     MOZ_ASSERT(false);
     return;
   }
   // Update pending frame count.
-  mPendingFrameCounts.Put(AsUint64(aWindowId), oldCount + 1);
+  count.mPendingCount = count.mPendingCount + 1;
+  mPendingFrameCounts.Put(AsUint64(aWindowId), count);
+}
+
+void
+RenderThread::IncRenderingFrameCount(wr::WindowId aWindowId)
+{
+  MutexAutoLock lock(mFrameCountMapLock);
+  // Get the old count.
+  FrameCount count;
+  if (!mPendingFrameCounts.Get(AsUint64(aWindowId), &count)) {
+    MOZ_ASSERT(false);
+    return;
+  }
+  // Update rendering frame count.
+  count.mRenderingCount = count.mRenderingCount + 1;
+  mPendingFrameCounts.Put(AsUint64(aWindowId), count);
 }
 
 void
 RenderThread::DecPendingFrameCount(wr::WindowId aWindowId)
 {
-  MutexAutoLock lock(mPendingFrameCountMapLock);
+  MutexAutoLock lock(mFrameCountMapLock);
   // Get the old count.
-  uint32_t oldCount = 0;
-  if (!mPendingFrameCounts.Get(AsUint64(aWindowId), &oldCount)) {
+  FrameCount count;
+  if (!mPendingFrameCounts.Get(AsUint64(aWindowId), &count)) {
     MOZ_ASSERT(false);
     return;
   }
-  MOZ_ASSERT(oldCount > 0);
-  if (oldCount <= 0) {
+  MOZ_ASSERT(count.mPendingCount > 0);
+  MOZ_ASSERT(count.mRenderingCount > 0);
+  if (count.mPendingCount <= 0) {
     return;
   }
-  // Update pending frame count.
-  mPendingFrameCounts.Put(AsUint64(aWindowId), oldCount - 1);
+  // Update frame counts.
+  count.mPendingCount = count.mPendingCount - 1;
+  count.mRenderingCount = count.mRenderingCount - 1;
+  mPendingFrameCounts.Put(AsUint64(aWindowId), count);
 }
 
 void
 RenderThread::RegisterExternalImage(uint64_t aExternalImageId, already_AddRefed<RenderTextureHost> aTexture)
 {
   MutexAutoLock lock(mRenderTextureMapLock);
 
   if (mHasShutdown) {
@@ -374,16 +405,17 @@ WebRenderThreadPool::~WebRenderThreadPoo
 
 } // namespace wr
 } // namespace mozilla
 
 extern "C" {
 
 void wr_notifier_new_frame_ready(mozilla::wr::WrWindowId aWindowId)
 {
+  mozilla::wr::RenderThread::Get()->IncRenderingFrameCount(aWindowId);
   mozilla::wr::RenderThread::Get()->NewFrameReady(mozilla::wr::WindowId(aWindowId));
 }
 
 void wr_notifier_new_scroll_frame_ready(mozilla::wr::WrWindowId aWindowId, bool aCompositeNeeded)
 {
   // It is not necessary to update rendering with new_scroll_frame_ready.
   // WebRenderBridgeParent::CompositeToTarget() is implemented to call
   // WebRenderAPI::GenerateFrame() if it is necessary to trigger UpdateAndRender().
--- a/gfx/webrender_bindings/RenderThread.h
+++ b/gfx/webrender_bindings/RenderThread.h
@@ -123,20 +123,22 @@ public:
 
   /// Can be called from any thread.
   void UnregisterExternalImage(uint64_t aExternalImageId);
 
   /// Can only be called from the render thread.
   RenderTextureHost* GetRenderTexture(WrExternalImageId aExternalImageId);
 
   /// Can be called from any thread.
-  uint32_t GetPendingFrameCount(wr::WindowId aWindowId);
+  bool TooManyPendingFrames(wr::WindowId aWindowId);
   /// Can be called from any thread.
   void IncPendingFrameCount(wr::WindowId aWindowId);
   /// Can be called from any thread.
+  void IncRenderingFrameCount(wr::WindowId aWindowId);
+  /// Can be called from any thread.
   void DecPendingFrameCount(wr::WindowId aWindowId);
 
   /// Can be called from any thread.
   WebRenderThreadPool& ThreadPool() { return mThreadPool; }
 
 private:
   explicit RenderThread(base::Thread* aThread);
 
@@ -146,18 +148,23 @@ private:
   ~RenderThread();
 
   base::Thread* const mThread;
 
   WebRenderThreadPool mThreadPool;
 
   std::map<wr::WindowId, UniquePtr<RendererOGL>> mRenderers;
 
-  Mutex mPendingFrameCountMapLock;
-  nsDataHashtable<nsUint64HashKey, uint32_t> mPendingFrameCounts;
+  struct FrameCount {
+    int64_t mPendingCount = 0;
+    int64_t mRenderingCount = 0;
+  };
+
+  Mutex mFrameCountMapLock;
+  nsDataHashtable<nsUint64HashKey, FrameCount> mPendingFrameCounts;
 
   Mutex mRenderTextureMapLock;
   nsRefPtrHashtable<nsUint64HashKey, RenderTextureHost> mRenderTextures;
   bool mHasShutdown;
 };
 
 } // namespace wr
 } // namespace mozilla