Bug 1341878. Separate out finishing the display list from sending it. r=sotaro
authorJeff Muizelaar <jmuizelaar@mozilla.com>
Thu, 23 Feb 2017 16:12:40 -0500
changeset 374800 3e6f3f29feeea936f222df376b0d7f706cd33a1f
parent 373509 2fcef8b1c4374728d95c3d72cf6e4fba76d69169
child 374801 c79c28db46db4e567f6c8fa918c31aa4f90ded86
push id10863
push userjlorenzo@mozilla.com
push dateMon, 06 Mar 2017 23:02:23 +0000
treeherdermozilla-aurora@0931190cd725 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssotaro
bugs1341878
milestone54.0a1
Bug 1341878. Separate out finishing the display list from sending it. r=sotaro This adds the size to the DPEnd command so that we can use it in SetRootDisplayList instead of storing it in WrState.
gfx/layers/ipc/PWebRenderBridge.ipdl
gfx/layers/wr/WebRenderBridgeChild.cpp
gfx/layers/wr/WebRenderBridgeChild.h
gfx/layers/wr/WebRenderBridgeParent.cpp
gfx/layers/wr/WebRenderBridgeParent.h
gfx/layers/wr/WebRenderLayerManager.cpp
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/PWebRenderBridge.ipdl
+++ b/gfx/layers/ipc/PWebRenderBridge.ipdl
@@ -33,18 +33,18 @@ parent:
   sync Create(IntSize aSize);
   sync AddImage(IntSize aSize, uint32_t aStride,
                 SurfaceFormat aFormat, ByteBuffer aBytes)
     returns (ImageKey aOutImageKey);
   sync UpdateImage(ImageKey aImageKey, IntSize aSize,
                    SurfaceFormat aFormat, ByteBuffer aBytes);
   sync DeleteImage(ImageKey aImageKey);
   async DPBegin(IntSize aSize);
-  async DPEnd(WebRenderCommand[] commands, OpDestroy[] toDestroy, uint64_t fwdTransactionId, uint64_t transactionId);
-  sync DPSyncEnd(WebRenderCommand[] commands, OpDestroy[] toDestroy, uint64_t fwdTransactionId, uint64_t transactionId);
+  async DPEnd(IntSize aSize, WebRenderCommand[] commands, OpDestroy[] toDestroy, uint64_t fwdTransactionId, uint64_t transactionId);
+  sync DPSyncEnd(IntSize aSize, WebRenderCommand[] commands, OpDestroy[] toDestroy, uint64_t fwdTransactionId, uint64_t transactionId);
   sync DPGetSnapshot(PTexture texture);
   async AddExternalImageId(uint64_t aImageId, CompositableHandle aHandle);
   async AddExternalImageIdForCompositable(uint64_t aImageId, CompositableHandle aHandle);
   async RemoveExternalImageId(uint64_t aImageId);
   async SetLayerObserverEpoch(uint64_t layerObserverEpoch);
   async ClearCachedResources();
 
   async Shutdown();
--- a/gfx/layers/wr/WebRenderBridgeChild.cpp
+++ b/gfx/layers/wr/WebRenderBridgeChild.cpp
@@ -63,24 +63,24 @@ WebRenderBridgeChild::DPBegin(const gfx:
 
   UpdateFwdTransactionId();
   this->SendDPBegin(aSize);
   mIsInTransaction = true;
   return true;
 }
 
 void
-WebRenderBridgeChild::DPEnd(bool aIsSync, uint64_t aTransactionId)
+WebRenderBridgeChild::DPEnd(const gfx::IntSize& aSize, bool aIsSync, uint64_t aTransactionId)
 {
   MOZ_ASSERT(!mDestroyed);
   MOZ_ASSERT(mIsInTransaction);
   if (aIsSync) {
-    this->SendDPSyncEnd(mCommands, mDestroyedActors, GetFwdTransactionId(), aTransactionId);
+    this->SendDPSyncEnd(aSize, mCommands, mDestroyedActors, GetFwdTransactionId(), aTransactionId);
   } else {
-    this->SendDPEnd(mCommands, mDestroyedActors, GetFwdTransactionId(), aTransactionId);
+    this->SendDPEnd(aSize, mCommands, mDestroyedActors, GetFwdTransactionId(), aTransactionId);
   }
 
   mCommands.Clear();
   mDestroyedActors.Clear();
   mIsInTransaction = false;
 }
 
 uint64_t
--- a/gfx/layers/wr/WebRenderBridgeChild.h
+++ b/gfx/layers/wr/WebRenderBridgeChild.h
@@ -29,17 +29,17 @@ class WebRenderBridgeChild final : publi
 
 public:
   explicit WebRenderBridgeChild(const wr::PipelineId& aPipelineId);
 
   void AddWebRenderCommand(const WebRenderCommand& aCmd);
   void AddWebRenderCommands(const nsTArray<WebRenderCommand>& aCommands);
 
   bool DPBegin(const  gfx::IntSize& aSize);
-  void DPEnd(bool aIsSync, uint64_t aTransactionId);
+  void DPEnd(const gfx::IntSize& aSize, bool aIsSync, uint64_t aTransactionId);
 
   CompositorBridgeChild* GetCompositorBridgeChild();
 
   // KnowsCompositor
   TextureForwarder* GetTextureForwarder() override;
   LayersIPCActor* GetLayersIPCActor() override;
 
   uint64_t AllocExternalImageId(const CompositableHandle& aHandle);
--- a/gfx/layers/wr/WebRenderBridgeParent.cpp
+++ b/gfx/layers/wr/WebRenderBridgeParent.cpp
@@ -104,17 +104,17 @@ WebRenderBridgeParent::RecvCreate(const 
   if (mDestroyed) {
     return IPC_OK();
   }
 
   if (mBuilder.isSome()) {
     return IPC_OK();
   }
   MOZ_ASSERT(mApi);
-  mBuilder.emplace(LayerIntSize(aSize.width, aSize.height), mPipelineId);
+  mBuilder.emplace(mPipelineId);
 
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
 WebRenderBridgeParent::RecvShutdown()
 {
   if (mDestroyed) {
@@ -190,64 +190,68 @@ WebRenderBridgeParent::RecvDPBegin(const
     return IPC_OK();
   }
   MOZ_ASSERT(mBuilder.isSome());
   mBuilder.ref().Begin(LayerIntSize(aSize.width, aSize.height));
   return IPC_OK();
 }
 
 void
-WebRenderBridgeParent::HandleDPEnd(InfallibleTArray<WebRenderCommand>&& aCommands,
+WebRenderBridgeParent::HandleDPEnd(const gfx::IntSize& aSize,
+                                 InfallibleTArray<WebRenderCommand>&& aCommands,
                                  InfallibleTArray<OpDestroy>&& aToDestroy,
                                  const uint64_t& aFwdTransactionId,
                                  const uint64_t& aTransactionId)
 {
   UpdateFwdTransactionId(aFwdTransactionId);
 
   if (mDestroyed) {
     for (const auto& op : aToDestroy) {
       DestroyActor(op);
     }
     return;
   }
   // This ensures that destroy operations are always processed. It is not safe
   // to early-return from RecvDPEnd without doing so.
   AutoWebRenderBridgeParentAsyncMessageSender autoAsyncMessageSender(this, &aToDestroy);
 
-  ProcessWebrenderCommands(aCommands, wr::NewEpoch(aTransactionId));
+  ProcessWebrenderCommands(aSize, aCommands, wr::NewEpoch(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.
   MOZ_ASSERT(aTransactionId == 1 || aTransactionId > mPendingTransactionId);
   mPendingTransactionId = aTransactionId;
 }
 
 mozilla::ipc::IPCResult
-WebRenderBridgeParent::RecvDPEnd(InfallibleTArray<WebRenderCommand>&& aCommands,
+WebRenderBridgeParent::RecvDPEnd(const gfx::IntSize& aSize,
+                                 InfallibleTArray<WebRenderCommand>&& aCommands,
                                  InfallibleTArray<OpDestroy>&& aToDestroy,
                                  const uint64_t& aFwdTransactionId,
                                  const uint64_t& aTransactionId)
 {
-  HandleDPEnd(Move(aCommands), Move(aToDestroy), aFwdTransactionId, aTransactionId);
+  HandleDPEnd(aSize, Move(aCommands), Move(aToDestroy), aFwdTransactionId, aTransactionId);
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
-WebRenderBridgeParent::RecvDPSyncEnd(InfallibleTArray<WebRenderCommand>&& aCommands,
+WebRenderBridgeParent::RecvDPSyncEnd(const gfx::IntSize &aSize,
+                                     InfallibleTArray<WebRenderCommand>&& aCommands,
                                      InfallibleTArray<OpDestroy>&& aToDestroy,
                                      const uint64_t& aFwdTransactionId,
                                      const uint64_t& aTransactionId)
 {
-  HandleDPEnd(Move(aCommands), Move(aToDestroy), aFwdTransactionId, aTransactionId);
+  HandleDPEnd(aSize, Move(aCommands), Move(aToDestroy), aFwdTransactionId, aTransactionId);
   return IPC_OK();
 }
 
 void
-WebRenderBridgeParent::ProcessWebrenderCommands(InfallibleTArray<WebRenderCommand>& aCommands, const wr::Epoch& aEpoch)
+WebRenderBridgeParent::ProcessWebrenderCommands(const gfx::IntSize &aSize,
+                                                InfallibleTArray<WebRenderCommand>& aCommands, const wr::Epoch& aEpoch)
 {
   MOZ_ASSERT(mBuilder.isSome());
   wr::DisplayListBuilder& builder = mBuilder.ref();
   // XXX remove it when external image key is used.
   std::vector<wr::ImageKey> keysToDelete;
 
   for (InfallibleTArray<WebRenderCommand>::index_type i = 0; i < aCommands.Length(); ++i) {
     const WebRenderCommand& cmd = aCommands[i];
@@ -401,17 +405,18 @@ WebRenderBridgeParent::ProcessWebrenderC
                               op.border_radius(),
                               op.clip_mode());
         break;
       }
       default:
         NS_RUNTIMEABORT("not reached");
     }
   }
-  builder.End(*mApi, aEpoch);
+  builder.End();
+  mApi->SetRootDisplayList(gfx::Color(0.3f, 0.f, 0.f, 1.f), aEpoch, LayerSize(aSize.width, aSize.height), builder);
 
   ScheduleComposition();
   DeleteOldImages();
 
   // XXX remove it when external image key is used.
   if (!keysToDelete.empty()) {
     mKeysToDelete.swap(keysToDelete);
   }
--- a/gfx/layers/wr/WebRenderBridgeParent.h
+++ b/gfx/layers/wr/WebRenderBridgeParent.h
@@ -66,21 +66,23 @@ public:
                                        const ByteBuffer& aBuffer,
                                        wr::ImageKey* aOutImageKey) override;
   mozilla::ipc::IPCResult RecvUpdateImage(const wr::ImageKey& aImageKey,
                                           const gfx::IntSize& aSize,
                                           const gfx::SurfaceFormat& aFormat,
                                           const ByteBuffer& aBuffer) override;
   mozilla::ipc::IPCResult RecvDeleteImage(const wr::ImageKey& a1) override;
   mozilla::ipc::IPCResult RecvDPBegin(const gfx::IntSize& aSize) override;
-  mozilla::ipc::IPCResult RecvDPEnd(InfallibleTArray<WebRenderCommand>&& aCommands,
+  mozilla::ipc::IPCResult RecvDPEnd(const gfx::IntSize& aSize,
+                                    InfallibleTArray<WebRenderCommand>&& aCommands,
                                     InfallibleTArray<OpDestroy>&& aToDestroy,
                                     const uint64_t& aFwdTransactionId,
                                     const uint64_t& aTransactionId) override;
-  mozilla::ipc::IPCResult RecvDPSyncEnd(InfallibleTArray<WebRenderCommand>&& aCommands,
+  mozilla::ipc::IPCResult RecvDPSyncEnd(const gfx::IntSize& aSize,
+                                        InfallibleTArray<WebRenderCommand>&& aCommands,
                                         InfallibleTArray<OpDestroy>&& aToDestroy,
                                         const uint64_t& aFwdTransactionId,
                                         const uint64_t& aTransactionId) override;
   mozilla::ipc::IPCResult RecvDPGetSnapshot(PTextureParent* aTexture) override;
 
   mozilla::ipc::IPCResult RecvAddExternalImageId(const uint64_t& aImageId,
                                                  const CompositableHandle& aHandle) override;
   mozilla::ipc::IPCResult RecvAddExternalImageIdForCompositable(const uint64_t& aImageId,
@@ -126,22 +128,23 @@ public:
     MOZ_ASSERT(mWidget);
     aNotifications->AppendElements(Move(mImageCompositeNotifications));
   }
 
 private:
   virtual ~WebRenderBridgeParent();
 
   void DeleteOldImages();
-  void ProcessWebrenderCommands(InfallibleTArray<WebRenderCommand>& commands, const wr::Epoch& aEpoch);
+  void ProcessWebrenderCommands(const gfx::IntSize &aSize, InfallibleTArray<WebRenderCommand>& commands, const wr::Epoch& aEpoch);
   void ScheduleComposition();
   void ClearResources();
   uint64_t GetChildLayerObserverEpoch() const { return mChildLayerObserverEpoch; }
   bool ShouldParentObserveEpoch();
-  void HandleDPEnd(InfallibleTArray<WebRenderCommand>&& aCommands,
+  void HandleDPEnd(const gfx::IntSize& aSize,
+                   InfallibleTArray<WebRenderCommand>&& aCommands,
                    InfallibleTArray<OpDestroy>&& aToDestroy,
                    const uint64_t& aFwdTransactionId,
                    const uint64_t& aTransactionId);
 
 private:
   CompositorBridgeParentBase* MOZ_NON_OWNING_REF mCompositorBridge;
   wr::PipelineId mPipelineId;
   RefPtr<widget::CompositorWidget> mWidget;
--- a/gfx/layers/wr/WebRenderLayerManager.cpp
+++ b/gfx/layers/wr/WebRenderLayerManager.cpp
@@ -311,17 +311,17 @@ WebRenderLayerManager::EndTransaction(Dr
     return;
   }
 
   WebRenderLayer::ToWebRenderLayer(mRoot)->RenderLayer();
 
   bool sync = mTarget != nullptr;
   mLatestTransactionId = mTransactionIdAllocator->GetTransactionId();
 
-  WrBridge()->DPEnd(sync, mLatestTransactionId);
+  WrBridge()->DPEnd(size.ToUnknownSize(), sync, mLatestTransactionId);
 
   MakeSnapshotIfRequired(size);
 
   // this may result in Layers being deleted, which results in
   // PLayer::Send__delete__() and DeallocShmem()
   mKeepAlive.Clear();
 }
 
--- a/gfx/webrender_bindings/WebRenderAPI.cpp
+++ b/gfx/webrender_bindings/WebRenderAPI.cpp
@@ -293,38 +293,38 @@ WebRenderAPI::SetProfilerEnabled(bool aE
 
 void
 WebRenderAPI::RunOnRenderThread(UniquePtr<RendererEvent> aEvent)
 {
   auto event = reinterpret_cast<uintptr_t>(aEvent.release());
   wr_api_send_external_event(mWrApi, event);
 }
 
-DisplayListBuilder::DisplayListBuilder(const LayerIntSize& aSize, PipelineId aId)
+DisplayListBuilder::DisplayListBuilder(PipelineId aId)
 {
   MOZ_COUNT_CTOR(DisplayListBuilder);
-  mWrState = wr_state_new(aSize.width, aSize.height, aId);
+  mWrState = wr_state_new(aId);
 }
 
 DisplayListBuilder::~DisplayListBuilder()
 {
   MOZ_COUNT_DTOR(DisplayListBuilder);
   wr_state_delete(mWrState);
 }
 
 void
 DisplayListBuilder::Begin(const LayerIntSize& aSize)
 {
   wr_dp_begin(mWrState, aSize.width, aSize.height);
 }
 
 void
-DisplayListBuilder::End(WebRenderAPI& aApi, Epoch aEpoch)
+DisplayListBuilder::End()
 {
-  wr_dp_end(mWrState, aApi.mWrApi, aEpoch);
+  wr_dp_end(mWrState);
 }
 
 void
 DisplayListBuilder::PushStackingContext(const WrRect& aBounds,
                                         const WrRect& aOverflow,
                                         const WrImageMask* aMask,
                                         const float aOpacity,
                                         const gfx::Matrix4x4& aTransform,
--- a/gfx/webrender_bindings/WebRenderAPI.h
+++ b/gfx/webrender_bindings/WebRenderAPI.h
@@ -91,24 +91,24 @@ protected:
   friend class DisplayListBuilder;
 };
 
 /// This is a simple C++ wrapper around WrState defined in the rust bindings.
 /// We may want to turn this into a direct wrapper on top of WebRenderFrameBuilder
 /// instead, so the interface may change a bit.
 class DisplayListBuilder {
 public:
-  DisplayListBuilder(const LayerIntSize& aSize, wr::PipelineId aId);
+  explicit DisplayListBuilder(wr::PipelineId aId);
   DisplayListBuilder(DisplayListBuilder&&) = default;
 
   ~DisplayListBuilder();
 
   void Begin(const LayerIntSize& aSize);
 
-  void End(WebRenderAPI& aApi, wr::Epoch aEpoch);
+  void End();
 
   void PushStackingContext(const WrRect& aBounds, // TODO: We should work with strongly typed rects
                            const WrRect& aOverflow,
                            const WrImageMask* aMask, // TODO: needs a wrapper.
                            const float aOpacity,
                            const gfx::Matrix4x4& aTransform,
                            const WrMixBlendMode& aMixBlendMode);
 
--- a/gfx/webrender_bindings/src/bindings.rs
+++ b/gfx/webrender_bindings/src/bindings.rs
@@ -219,21 +219,20 @@ pub extern fn wr_window_new(window_id: W
 
     *out_api = Box::into_raw(Box::new(sender.create_api()));
     *out_renderer = Box::into_raw(Box::new(renderer));
 
     return true;
 }
 
 #[no_mangle]
-pub extern fn wr_state_new(width: u32, height: u32, pipeline_id: PipelineId) -> *mut WrState {
+pub extern fn wr_state_new(pipeline_id: PipelineId) -> *mut WrState {
     assert!(unsafe { is_in_compositor_thread() });
 
     let state = Box::new(WrState {
-        size: (width, height),
         pipeline_id: pipeline_id,
         z_index: 0,
         frame_builder: WebRenderFrameBuilder::new(pipeline_id),
     });
 
     Box::into_raw(state)
 }
 
@@ -244,17 +243,16 @@ pub extern fn wr_state_delete(state:*mut
     unsafe {
         Box::from_raw(state);
     }
 }
 
 #[no_mangle]
 pub extern fn wr_dp_begin(state: &mut WrState, width: u32, height: u32) {
     assert!( unsafe { is_in_compositor_thread() });
-    state.size = (width, height);
     state.frame_builder.dl_builder.list.clear();
     state.z_index = 0;
 
     let bounds = LayoutRect::new(LayoutPoint::new(0.0, 0.0), LayoutSize::new(width as f32, height as f32));
 
     state.frame_builder.dl_builder.push_stacking_context(
         webrender_traits::ScrollPolicy::Scrollable,
         bounds,
@@ -263,33 +261,19 @@ pub extern fn wr_dp_begin(state: &mut Wr
         PropertyBinding::Value(LayoutTransform::identity()),
         LayoutTransform::identity(),
         webrender_traits::MixBlendMode::Normal,
         Vec::new(),
     );
 }
 
 #[no_mangle]
-pub extern fn wr_dp_end(state: &mut WrState, api: &mut RenderApi, epoch: u32) {
+pub extern fn wr_dp_end(state: &mut WrState) {
     assert!( unsafe { is_in_compositor_thread() });
-    let root_background_color = ColorF::new(0.3, 0.0, 0.0, 1.0);
-    let pipeline_id = state.pipeline_id;
-    let (width, height) = state.size;
-
     state.frame_builder.dl_builder.pop_stacking_context();
-
-    let fb = mem::replace(&mut state.frame_builder, WebRenderFrameBuilder::new(pipeline_id));
-
-    let preserve_frame_state = true;
-    api.set_root_display_list(Some(root_background_color),
-                              Epoch(epoch),
-                              LayoutSize::new(width as f32, height as f32),
-                              fb.dl_builder,
-                              preserve_frame_state);
-    api.generate_frame(None);
 }
 
 #[no_mangle]
 pub unsafe extern fn wr_renderer_flush_rendered_epochs(renderer: &mut Renderer) -> *mut Vec<(PipelineId, Epoch)> {
     let map = renderer.flush_rendered_epochs();
     let pipeline_epochs = Box::new(map.into_iter().collect());
     return Box::into_raw(pipeline_epochs);
 }
@@ -365,17 +349,16 @@ impl WebRenderFrameBuilder {
         WebRenderFrameBuilder {
             root_pipeline_id: root_pipeline_id,
             dl_builder: webrender_traits::DisplayListBuilder::new(root_pipeline_id),
         }
     }
 }
 
 pub struct WrState {
-    size: (u32, u32),
     pipeline_id: PipelineId,
     z_index: i32,
     frame_builder: WebRenderFrameBuilder,
 }
 
 #[repr(C)]
 enum WrExternalImageType {
     TEXTURE_HANDLE,
--- a/gfx/webrender_bindings/webrender_ffi.h
+++ b/gfx/webrender_bindings/webrender_ffi.h
@@ -449,17 +449,17 @@ WR_INLINE void
 wr_api_send_external_event(WrAPI* api, uintptr_t evt)
 WR_DESTRUCTOR_SAFE_FUNC;
 
 WR_INLINE WrFontKey
 wr_api_add_raw_font(WrAPI* api, uint8_t* font_buffer, size_t buffer_size)
 WR_FUNC;
 
 WR_INLINE WrState*
-wr_state_new(uint32_t width, uint32_t height, WrPipelineId pipeline_id)
+wr_state_new(WrPipelineId pipeline_id)
 WR_FUNC;
 
 WR_INLINE void
 wr_state_delete(WrState* state)
 WR_DESTRUCTOR_SAFE_FUNC;
 
 WR_INLINE void
 wr_dp_push_stacking_context(WrState *wrState, WrRect bounds,
@@ -483,17 +483,17 @@ wr_dp_pop_scroll_layer(WrState *wrState)
 WR_FUNC;
 
 
 WR_INLINE void
 wr_dp_begin(WrState* wrState, uint32_t width, uint32_t height)
 WR_FUNC;
 
 WR_INLINE void
-wr_dp_end(WrState* builder, WrAPI* api, WrEpoch epoch)
+wr_dp_end(WrState* wrState)
 WR_FUNC;
 
 WR_INLINE void
 wr_dp_push_rect(WrState* wrState, WrRect bounds, WrRect clip,
                 WrColor color)
 WR_FUNC;
 
 WR_INLINE void