Bug 1342380 - Enable VsyncScheduler again r=kats
authorsotaro <sotaro.ikeda.g@gmail.com>
Mon, 27 Feb 2017 09:27:04 +0900
changeset 490121 99933cb429cee01c317287843ce686ea18a8aeb6
parent 490120 6237f9ee107b9c4fafd2aa495d7a47f51d0221d3
child 490122 709f9115cd7022ca78a5f448934acce353fe9f34
push id47003
push userkgupta@mozilla.com
push dateMon, 27 Feb 2017 17:43:51 +0000
reviewerskats
bugs1342380
milestone54.0a1
Bug 1342380 - Enable VsyncScheduler again r=kats
gfx/layers/ipc/CompositorBridgeParent.cpp
gfx/layers/ipc/CrossProcessCompositorBridgeParent.cpp
gfx/layers/wr/WebRenderBridgeParent.cpp
gfx/layers/wr/WebRenderBridgeParent.h
gfx/webrender_bindings/WebRenderAPI.cpp
gfx/webrender_bindings/WebRenderAPI.h
gfx/webrender_bindings/src/bindings.rs
gfx/webrender_bindings/webrender_ffi.h
--- a/gfx/layers/ipc/CompositorBridgeParent.cpp
+++ b/gfx/layers/ipc/CompositorBridgeParent.cpp
@@ -1587,17 +1587,17 @@ CompositorBridgeParent::AllocPWebRenderB
 
   MOZ_ASSERT(mWidget);
   RefPtr<widget::CompositorWidget> widget = mWidget;
   RefPtr<wr::WebRenderAPI> api = wr::WebRenderAPI::Create(gfxPrefs::WebRenderProfilerEnabled(), this, Move(widget));
   RefPtr<WebRenderCompositableHolder> holder = new WebRenderCompositableHolder();
   MOZ_ASSERT(api); // TODO have a fallback
   api->SetRootPipeline(aPipelineId);
   *aIdNamespace = api->GetNamespace().mHandle;
-  mWrBridge = new WebRenderBridgeParent(this, aPipelineId, mWidget, Move(api), Move(holder));
+  mWrBridge = new WebRenderBridgeParent(this, aPipelineId, mWidget, nullptr, Move(api), Move(holder));
 
   mCompositorScheduler = mWrBridge->CompositorScheduler();
   MOZ_ASSERT(mCompositorScheduler);
   mWrBridge.get()->AddRef(); // IPDL reference
   MonitorAutoLock lock(*sIndirectLayerTreesLock);
   auto pipelineHandle = aPipelineId.mHandle;
   MOZ_ASSERT(sIndirectLayerTrees[pipelineHandle].mWrBridge == nullptr);
   sIndirectLayerTrees[pipelineHandle].mWrBridge = mWrBridge;
--- a/gfx/layers/ipc/CrossProcessCompositorBridgeParent.cpp
+++ b/gfx/layers/ipc/CrossProcessCompositorBridgeParent.cpp
@@ -217,17 +217,17 @@ CrossProcessCompositorBridgeParent::Allo
   MOZ_ASSERT(sIndirectLayerTrees.find(pipelineHandle) != sIndirectLayerTrees.end());
   MOZ_ASSERT(sIndirectLayerTrees[pipelineHandle].mWrBridge == nullptr);
   CompositorBridgeParent* cbp = sIndirectLayerTrees[pipelineHandle].mParent;
   WebRenderBridgeParent* root = sIndirectLayerTrees[cbp->RootLayerTreeId()].mWrBridge.get();
 
   WebRenderBridgeParent* parent = nullptr;
   RefPtr<wr::WebRenderAPI> api = root->GetWebRenderAPI();
   RefPtr<WebRenderCompositableHolder> holder = root->CompositableHolder();
-  parent = new WebRenderBridgeParent(this, aPipelineId, nullptr, Move(api), Move(holder));
+  parent = new WebRenderBridgeParent(this, aPipelineId, nullptr, root->CompositorScheduler(), Move(api), Move(holder));
 
   parent->AddRef(); // IPDL reference
   sIndirectLayerTrees[pipelineHandle].mCrossProcessParent = this;
   sIndirectLayerTrees[pipelineHandle].mWrBridge = parent;
   *aTextureFactoryIdentifier = parent->GetTextureFactoryIdentifier();
   *aIdNamespace = api->GetNamespace().mHandle;
   return parent;
 }
--- a/gfx/layers/wr/WebRenderBridgeParent.cpp
+++ b/gfx/layers/wr/WebRenderBridgeParent.cpp
@@ -73,31 +73,34 @@ public:
 private:
   WebRenderBridgeParent* mWebRenderBridgeParent;
   InfallibleTArray<OpDestroy>* mActorsToDestroy;
 };
 
 WebRenderBridgeParent::WebRenderBridgeParent(CompositorBridgeParentBase* aCompositorBridge,
                                              const wr::PipelineId& aPipelineId,
                                              widget::CompositorWidget* aWidget,
+                                             CompositorVsyncScheduler* aScheduler,
                                              RefPtr<wr::WebRenderAPI>&& aApi,
                                              RefPtr<WebRenderCompositableHolder>&& aHolder)
   : mCompositorBridge(aCompositorBridge)
   , mPipelineId(aPipelineId)
   , mWidget(aWidget)
   , mBuilder(Nothing())
   , mApi(aApi)
   , mCompositableHolder(aHolder)
+  , mCompositorScheduler(aScheduler)
   , mChildLayerObserverEpoch(0)
   , mParentLayerObserverEpoch(0)
   , mWrEpoch(0)
   , mDestroyed(false)
 {
   MOZ_ASSERT(mCompositableHolder);
   if (mWidget) {
+    MOZ_ASSERT(!mCompositorScheduler);
     mCompositorScheduler = new CompositorVsyncScheduler(this, mWidget);
   }
 }
 
 
 mozilla::ipc::IPCResult
 WebRenderBridgeParent::RecvCreate(const gfx::IntSize& aSize)
 {
@@ -466,16 +469,21 @@ WebRenderBridgeParent::RecvDPGetSnapshot
   // We only support B8G8R8A8 for now.
   MOZ_ASSERT(buffer);
   MOZ_ASSERT(bufferTexture->GetFormat() == SurfaceFormat::B8G8R8A8);
   uint32_t buffer_size = size.width * size.height * 4;
 
   // Assert the stride of the buffer is what webrender expects
   MOZ_ASSERT((uint32_t)(size.width * 4) == stride);
 
+  if (mCompositorScheduler->NeedsComposite()) {
+    mCompositorScheduler->CancelCurrentCompositeTask();
+    mCompositorScheduler->ForceComposeToTarget(nullptr, nullptr);
+  }
+
   MOZ_ASSERT(mBuilder.isSome());
   mApi->Readback(size, buffer, buffer_size);
 
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
 WebRenderBridgeParent::RecvAddExternalImageId(const uint64_t& aImageId,
@@ -563,19 +571,17 @@ void
 WebRenderBridgeParent::ActorDestroy(ActorDestroyReason aWhy)
 {
   Destroy();
 }
 
 void
 WebRenderBridgeParent::CompositeToTarget(gfx::DrawTarget* aTarget, const gfx::IntRect* aRect)
 {
-  // TODO(bug 1328602) With the RenderThread, calling SetRootStackingContext
-  // should trigger the composition on the render thread.
-  MOZ_ASSERT_UNREACHABLE("unexpected to be called");
+  mApi->GenerateFrame();
 }
 
 void
 WebRenderBridgeParent::HoldPendingTransactionId(uint32_t aWrEpoch, uint64_t aTransactionId)
 {
   // The transaction ID might get reset to 1 if the page gets reloaded, see
   // https://bugzilla.mozilla.org/show_bug.cgi?id=1145295#c41
   // Otherwise, it should be continually increasing.
@@ -636,21 +642,19 @@ WebRenderBridgeParent::DeleteOldImages()
     mApi->DeleteImage(key);
   }
   mKeysToDelete.clear();
 }
 
 void
 WebRenderBridgeParent::ScheduleComposition()
 {
-  MOZ_ASSERT(mApi);
-  // TODO(bug 1328602) should probably send a message to the render
-  // thread and force rendering, although in most cases where this is
-  // called, rendering should be triggered automatically already (maybe
-  // not in the ImageBridge case).
+  if (mCompositorScheduler) {
+    mCompositorScheduler->ScheduleComposition();
+  }
 }
 
 void
 WebRenderBridgeParent::ClearResources()
 {
   DeleteOldImages();
   if (mCompositableHolder) {
     for (auto iter = mExternalImageIds.Iter(); !iter.Done(); iter.Next()) {
@@ -658,21 +662,20 @@ WebRenderBridgeParent::ClearResources()
       mCompositableHolder->RemoveExternalImageId(externalImageId);
     }
   }
   mExternalImageIds.Clear();
 
   if (mBuilder.isSome()) {
     mBuilder.reset();
   }
-  if (mCompositorScheduler) {
+  if (mWidget && mCompositorScheduler) {
     mCompositorScheduler->Destroy();
-    mCompositorScheduler = nullptr;
   }
-
+  mCompositorScheduler = nullptr;
   mApi = nullptr;
   mCompositorBridge = nullptr;
 }
 
 bool
 WebRenderBridgeParent::ShouldParentObserveEpoch()
 {
   if (mParentLayerObserverEpoch == mChildLayerObserverEpoch) {
--- a/gfx/layers/wr/WebRenderBridgeParent.h
+++ b/gfx/layers/wr/WebRenderBridgeParent.h
@@ -41,16 +41,17 @@ class WebRenderCompositableHolder;
 class WebRenderBridgeParent final : public PWebRenderBridgeParent
                                   , public CompositorVsyncSchedulerOwner
                                   , public CompositableParentManager
 {
 public:
   WebRenderBridgeParent(CompositorBridgeParentBase* aCompositorBridge,
                         const wr::PipelineId& aPipelineId,
                         widget::CompositorWidget* aWidget,
+                        CompositorVsyncScheduler* aScheduler,
                         RefPtr<wr::WebRenderAPI>&& aApi,
                         RefPtr<WebRenderCompositableHolder>&& aHolder);
 
   wr::PipelineId PipelineId() { return mPipelineId; }
   wr::WebRenderAPI* GetWebRenderAPI() { return mApi; }
   WebRenderCompositableHolder* CompositableHolder() { return mCompositableHolder; }
   CompositorVsyncScheduler* CompositorScheduler() { return mCompositorScheduler.get(); }
 
--- a/gfx/webrender_bindings/WebRenderAPI.cpp
+++ b/gfx/webrender_bindings/WebRenderAPI.cpp
@@ -146,16 +146,22 @@ WebRenderAPI::~WebRenderAPI()
   auto event = MakeUnique<RemoveRenderer>(&task);
   RunOnRenderThread(Move(event));
   task.Wait();
 
   wr_api_delete(mWrApi);
 }
 
 void
+WebRenderAPI::GenerateFrame()
+{
+  wr_api_generate_frame(mWrApi);
+}
+
+void
 WebRenderAPI::SetRootDisplayList(gfx::Color aBgColor,
                                  Epoch aEpoch,
                                  LayerSize aViewportSize,
                                  DisplayListBuilder& aBuilder)
 {
   wr_api_set_root_display_list(mWrApi, aBuilder.mWrState,
                                aEpoch,
                                aViewportSize.width, aViewportSize.height);
--- a/gfx/webrender_bindings/WebRenderAPI.h
+++ b/gfx/webrender_bindings/WebRenderAPI.h
@@ -36,16 +36,18 @@ class WebRenderAPI
 public:
   /// This can be called on the compositor thread only.
   static already_AddRefed<WebRenderAPI> Create(bool aEnableProfiler,
                                                layers::CompositorBridgeParentBase* aBridge,
                                                RefPtr<widget::CompositorWidget>&& aWidget);
 
   wr::WindowId GetId() const { return mId; }
 
+  void GenerateFrame();
+
   void SetRootDisplayList(gfx::Color aBgColor,
                           wr::Epoch aEpoch,
                           LayerSize aViewportSize,
                           DisplayListBuilder& aBuilder);
 
   void SetRootPipeline(wr::PipelineId aPipeline);
 
   void AddImage(wr::ImageKey aKey,
--- a/gfx/webrender_bindings/src/bindings.rs
+++ b/gfx/webrender_bindings/src/bindings.rs
@@ -163,17 +163,21 @@ pub unsafe extern fn wr_api_set_root_dis
     // but I suppose it is a good default.
     let preserve_frame_state = true;
     //let (dl_builder, aux_builder) = fb.dl_builder.finalize();
     api.set_root_display_list(Some(root_background_color),
                               epoch,
                               LayoutSize::new(viewport_width, viewport_height),
                               frame_builder.dl_builder,
                               preserve_frame_state);
-    api.generate_frame(None);
+}
+
+#[no_mangle]
+pub extern fn wr_api_generate_frame(api: &mut RenderApi) {
+  api.generate_frame(None);
 }
 
 // Call MakeCurrent before this.
 #[no_mangle]
 pub extern fn wr_window_new(window_id: WrWindowId,
                             gl_context: *mut c_void,
                             enable_profiler: bool,
                             external_image_handler: *mut WrExternalImageHandler,
--- a/gfx/webrender_bindings/webrender_ffi.h
+++ b/gfx/webrender_bindings/webrender_ffi.h
@@ -442,16 +442,20 @@ WR_INLINE void
 wr_api_set_root_pipeline(WrAPI* api, WrPipelineId pipeline_id)
 WR_FUNC;
 
 WR_INLINE void
 wr_api_set_root_display_list(WrAPI* api, WrState* state, WrEpoch epoch, float w, float h)
 WR_FUNC;
 
 WR_INLINE void
+wr_api_generate_frame(WrAPI* api)
+WR_FUNC;
+
+WR_INLINE void
 wr_api_send_external_event(WrAPI* api, uintptr_t evt)
 WR_DESTRUCTOR_SAFE_FUNC;
 
 WR_INLINE void
 wr_api_add_raw_font(WrAPI* api, WrFontKey key, uint8_t* font_buffer, size_t buffer_size)
 WR_FUNC;
 
 WR_INLINE WrState*