Bug 1581240 - Add an API to retrieve the collected frames from WebRender r=mstange
authorBarret Rennie <barret@brennie.ca>
Thu, 07 Nov 2019 22:34:49 +0000
changeset 501191 34d96c88ee69636384f3ae89c58a50274ac95f5b
parent 501190 a11afd00e52d20239fe704c219e4106ef8dd284e
child 501192 8e822bb904b1a2a4846c51ecbae38335aec268ec
push id114168
push userdluca@mozilla.com
push dateSun, 10 Nov 2019 03:08:55 +0000
treeherdermozilla-inbound@33f64c1ef3e4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmstange
bugs1581240
milestone72.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 1581240 - Add an API to retrieve the collected frames from WebRender r=mstange Differential Revision: https://phabricator.services.mozilla.com/D47816
gfx/layers/wr/WebRenderBridgeParent.cpp
gfx/layers/wr/WebRenderBridgeParent.h
gfx/webrender_bindings/RenderThread.cpp
gfx/webrender_bindings/RenderThread.h
gfx/webrender_bindings/WebRenderAPI.cpp
gfx/webrender_bindings/WebRenderAPI.h
--- a/gfx/layers/wr/WebRenderBridgeParent.cpp
+++ b/gfx/layers/wr/WebRenderBridgeParent.cpp
@@ -1030,16 +1030,21 @@ void WebRenderBridgeParent::SetCompositi
   Api(wr::RenderRoot::Default)->SetCompositionRecorder(std::move(aRecorder));
 }
 
 RefPtr<wr::WebRenderAPI::WriteCollectedFramesPromise>
 WebRenderBridgeParent::WriteCollectedFrames() {
   return Api(wr::RenderRoot::Default)->WriteCollectedFrames();
 }
 
+RefPtr<wr::WebRenderAPI::GetCollectedFramesPromise>
+WebRenderBridgeParent::GetCollectedFrames() {
+  return Api(wr::RenderRoot::Default)->GetCollectedFrames();
+}
+
 CompositorBridgeParent* WebRenderBridgeParent::GetRootCompositorBridgeParent()
     const {
   if (!mCompositorBridge) {
     return nullptr;
   }
 
   if (IsRootWebRenderBridgeParent()) {
     // This WebRenderBridgeParent is attached to the root
--- a/gfx/layers/wr/WebRenderBridgeParent.h
+++ b/gfx/layers/wr/WebRenderBridgeParent.h
@@ -300,16 +300,24 @@ class WebRenderBridgeParent final
 
 #if defined(MOZ_WIDGET_ANDROID)
   /**
    * Request a screengrab for android
    */
   void RequestScreenPixels(UiCompositorControllerParent* aController);
   void MaybeCaptureScreenPixels();
 #endif
+  /**
+   * Return the frames collected by the |WebRenderCompositionRecorder| encoded
+   * as data URIs.
+   *
+   * If there is not currently a recorder, this is a no-op and the promise will
+   * be rejected.
+   */
+  RefPtr<wr::WebRenderAPI::GetCollectedFramesPromise> GetCollectedFrames();
 
  private:
   class ScheduleSharedSurfaceRelease;
 
   explicit WebRenderBridgeParent(const wr::PipelineId& aPipelineId);
   virtual ~WebRenderBridgeParent();
 
   wr::WebRenderAPI* Api(wr::RenderRoot aRenderRoot) {
--- a/gfx/webrender_bindings/RenderThread.cpp
+++ b/gfx/webrender_bindings/RenderThread.cpp
@@ -264,16 +264,44 @@ void RenderThread::WriteCollectedFramesF
       wr_renderer_release_composition_recorder_structures(
           renderer->GetRenderer());
     }
 
     mCompositionRecorders.erase(it);
   }
 }
 
+Maybe<layers::CollectedFrames> RenderThread::GetCollectedFramesForWindow(
+    wr::WindowId aWindowId) {
+  MOZ_ASSERT(IsInRenderThread());
+
+  RendererOGL* renderer = GetRenderer(aWindowId);
+  MOZ_ASSERT(renderer);
+
+  auto it = mCompositionRecorders.find(aWindowId);
+  MOZ_DIAGNOSTIC_ASSERT(
+      it != mCompositionRecorders.end(),
+      "Attempted to get frames from a window that was not recording.");
+
+  Maybe<layers::CollectedFrames> maybeFrames;
+
+  if (it != mCompositionRecorders.end()) {
+    maybeFrames.emplace(it->second->GetCollectedFrames());
+
+    if (renderer) {
+      wr_renderer_release_composition_recorder_structures(
+          renderer->GetRenderer());
+    }
+
+    mCompositionRecorders.erase(it);
+  }
+
+  return maybeFrames;
+}
+
 void RenderThread::HandleFrameOneDoc(wr::WindowId aWindowId, bool aRender) {
   if (mHasShutdown) {
     return;
   }
 
   if (!IsInRenderThread()) {
     Loop()->PostTask(NewRunnableMethod<wr::WindowId, bool>(
         "wr::RenderThread::HandleFrameOneDoc", this,
--- a/gfx/webrender_bindings/RenderThread.h
+++ b/gfx/webrender_bindings/RenderThread.h
@@ -11,16 +11,17 @@
 #include "base/platform_thread.h"  // for PlatformThreadId
 #include "base/thread.h"           // for Thread
 #include "base/message_loop.h"
 #include "nsISupportsImpl.h"
 #include "ThreadSafeRefcountingWithMainThreadDestruction.h"
 #include "mozilla/gfx/Point.h"
 #include "mozilla/MozPromise.h"
 #include "mozilla/DataMutex.h"
+#include "mozilla/Maybe.h"
 #include "mozilla/webrender/webrender_ffi.h"
 #include "mozilla/UniquePtr.h"
 #include "mozilla/webrender/WebRenderTypes.h"
 #include "mozilla/layers/SynchronousTask.h"
 #include "mozilla/layers/WebRenderCompositionRecorder.h"
 #include "mozilla/VsyncDispatcher.h"
 
 #include <list>
@@ -266,16 +267,19 @@ class RenderThread final {
   size_t RendererCount();
 
   void SetCompositionRecorderForWindow(
       wr::WindowId aWindowId,
       UniquePtr<layers::WebRenderCompositionRecorder> aCompositionRecorder);
 
   void WriteCollectedFramesForWindow(wr::WindowId aWindowId);
 
+  Maybe<layers::CollectedFrames> GetCollectedFramesForWindow(
+      wr::WindowId aWindowId);
+
  private:
   explicit RenderThread(base::Thread* aThread);
 
   void DeferredRenderTextureHostDestroy();
   void ShutDownTask(layers::SynchronousTask* aTask);
   void InitDeviceTask();
 
   void DoAccumulateMemoryReport(MemoryReport,
--- a/gfx/webrender_bindings/WebRenderAPI.cpp
+++ b/gfx/webrender_bindings/WebRenderAPI.cpp
@@ -646,16 +646,52 @@ WebRenderAPI::WriteCollectedFrames() {
 
   auto event = MakeUnique<WriteCollectedFramesEvent>();
   auto promise = event->GetPromise();
 
   RunOnRenderThread(std::move(event));
   return promise;
 }
 
+RefPtr<WebRenderAPI::GetCollectedFramesPromise>
+WebRenderAPI::GetCollectedFrames() {
+  class GetCollectedFramesEvent final : public RendererEvent {
+   public:
+    explicit GetCollectedFramesEvent() {
+      MOZ_COUNT_CTOR(GetCollectedFramesEvent);
+    }
+
+    ~GetCollectedFramesEvent() { MOZ_COUNT_DTOR(GetCollectedFramesEvent); };
+
+    void Run(RenderThread& aRenderThread, WindowId aWindowId) override {
+      Maybe<layers::CollectedFrames> frames =
+          aRenderThread.GetCollectedFramesForWindow(aWindowId);
+
+      if (frames) {
+        mPromise.Resolve(std::move(*frames), __func__);
+      } else {
+        mPromise.Reject(NS_ERROR_UNEXPECTED, __func__);
+      }
+    }
+
+    RefPtr<WebRenderAPI::GetCollectedFramesPromise> GetPromise() {
+      return mPromise.Ensure(__func__);
+    }
+
+   private:
+    MozPromiseHolder<WebRenderAPI::GetCollectedFramesPromise> mPromise;
+  };
+
+  auto event = MakeUnique<GetCollectedFramesEvent>();
+  auto promise = event->GetPromise();
+
+  RunOnRenderThread(std::move(event));
+  return promise;
+}
+
 void TransactionBuilder::Clear() { wr_resource_updates_clear(mTxn); }
 
 void TransactionBuilder::Notify(wr::Checkpoint aWhen,
                                 UniquePtr<NotificationHandler> aEvent) {
   wr_transaction_notify(mTxn, aWhen,
                         reinterpret_cast<uintptr_t>(aEvent.release()));
 }
 
--- a/gfx/webrender_bindings/WebRenderAPI.h
+++ b/gfx/webrender_bindings/WebRenderAPI.h
@@ -265,24 +265,35 @@ class WebRenderAPI final {
 
   void Capture();
   void SetTransactionLogging(bool aValue);
 
   void SetCompositionRecorder(
       UniquePtr<layers::WebRenderCompositionRecorder> aRecorder);
 
   typedef MozPromise<bool, nsresult, true> WriteCollectedFramesPromise;
+  typedef MozPromise<layers::CollectedFrames, nsresult, true>
+      GetCollectedFramesPromise;
 
   /**
    * Write the frames collected by the |WebRenderCompositionRecorder| to disk.
    *
    * If there is not currently a recorder, this is a no-op.
    */
   RefPtr<WriteCollectedFramesPromise> WriteCollectedFrames();
 
+  /**
+   * Return the frames collected by the |WebRenderCompositionRecorder| encoded
+   * as data URIs.
+   *
+   * If there is not currently a recorder, this is a no-op and the promise will
+   * be rejected.
+   */
+  RefPtr<GetCollectedFramesPromise> GetCollectedFrames();
+
  protected:
   WebRenderAPI(wr::DocumentHandle* aHandle, wr::WindowId aId,
                uint32_t aMaxTextureSize, bool aUseANGLE, bool aUseDComp,
                bool aUseTripleBuffering, layers::SyncHandle aSyncHandle,
                wr::RenderRoot aRenderRoot);
 
   ~WebRenderAPI();
   // Should be used only for shutdown handling