Bug 1406507. Move the displaylist ByteBuf into a Vec instead of copying. r=kats
authorJeff Muizelaar <jmuizelaar@mozilla.com>
Thu, 30 Nov 2017 18:14:41 -0500
changeset 706131 bdfdf0fa188910163d001272cc535f1b497431a1
parent 706130 4a31601120ad6fecef1b3f1836cf15124eaf86ba
child 706132 492835cff9328bf33dd11eda60eb486f67f1aec6
child 706238 39415e11a161cd51a623a2ea4fb34177b726819d
child 706407 4fa6204ac8b59db38b97b4fe6666f4c89ec65c69
push id91730
push usercholler@mozilla.com
push dateFri, 01 Dec 2017 12:27:59 +0000
reviewerskats
bugs1406507
milestone59.0a1
Bug 1406507. Move the displaylist ByteBuf into a Vec instead of copying. r=kats This eliminates a copy of the displaylist on the compositor thread. DONTBUILD
gfx/layers/wr/AsyncImagePipelineManager.cpp
gfx/layers/wr/WebRenderBridgeParent.cpp
gfx/webrender_bindings/WebRenderAPI.cpp
gfx/webrender_bindings/WebRenderAPI.h
gfx/webrender_bindings/WebRenderTypes.cpp
gfx/webrender_bindings/WebRenderTypes.h
gfx/webrender_bindings/moz.build
gfx/webrender_bindings/src/bindings.rs
gfx/webrender_bindings/webrender_ffi_generated.h
--- a/gfx/layers/wr/AsyncImagePipelineManager.cpp
+++ b/gfx/layers/wr/AsyncImagePipelineManager.cpp
@@ -348,17 +348,17 @@ AsyncImagePipelineManager::ApplyAsyncIma
     }
     builder.PopStackingContext();
 
     wr::BuiltDisplayList dl;
     wr::LayoutSize builderContentSize;
     builder.Finalize(builderContentSize, dl);
     mApi->SetDisplayList(gfx::Color(0.f, 0.f, 0.f, 0.f), epoch, LayerSize(pipeline->mScBounds.Width(), pipeline->mScBounds.Height()),
                          pipelineId, builderContentSize,
-                         dl.dl_desc, dl.dl.inner.data, dl.dl.inner.length,
+                         dl.dl_desc, dl.dl,
                          resourceUpdates);
   }
 }
 
 void
 AsyncImagePipelineManager::HoldExternalImage(const wr::PipelineId& aPipelineId, const wr::Epoch& aEpoch, WebRenderTextureHost* aTexture)
 {
   if (mDestroyed) {
--- a/gfx/layers/wr/WebRenderBridgeParent.cpp
+++ b/gfx/layers/wr/WebRenderBridgeParent.cpp
@@ -109,16 +109,17 @@ gecko_profiler_register_thread(const cha
 
 void
 gecko_profiler_unregister_thread()
 {
   PROFILER_UNREGISTER_THREAD();
 }
 
 namespace mozilla {
+
 namespace layers {
 
 using namespace mozilla::gfx;
 
 class MOZ_STACK_CLASS AutoWebRenderBridgeParentAsyncMessageSender
 {
 public:
   explicit AutoWebRenderBridgeParentAsyncMessageSender(WebRenderBridgeParent* aWebRenderBridgeParent,
@@ -593,28 +594,31 @@ WebRenderBridgeParent::RecvSetDisplayLis
   mAsyncImageManager->SetCompositionTime(TimeStamp::Now());
   ProcessWebRenderParentCommands(aCommands);
 
   wr::ResourceUpdateQueue resources;
   if (!UpdateResources(aResourceUpdates, aSmallShmems, aLargeShmems, resources)) {
     return IPC_FAIL(this, "Failed to deserialize resource updates");
   }
 
+
+  wr::Vec_u8 dlData(Move(dl));
+
   // If id namespaces do not match, it means the command is obsolete, probably
   // because the tab just moved to a new window.
   // In that case do not send the commands to webrender.
   if (mIdNamespace == aIdNamespace) {
     if (mWidget) {
       LayoutDeviceIntSize size = mWidget->GetClientSize();
       mApi->SetWindowParameters(size);
     }
     gfx::Color clearColor(0.f, 0.f, 0.f, 0.f);
     mApi->SetDisplayList(clearColor, wr::NewEpoch(wrEpoch), LayerSize(aSize.width, aSize.height),
                         mPipelineId, aContentSize,
-                        dlDesc, dl.mData, dl.mLen,
+                        dlDesc, dlData,
                         resources);
 
     ScheduleGenerateFrame();
 
     if (ShouldParentObserveEpoch()) {
       mCompositorBridge->ObserveLayerUpdate(GetLayersId(), GetChildLayerObserverEpoch(), true);
     }
   }
--- a/gfx/webrender_bindings/WebRenderAPI.cpp
+++ b/gfx/webrender_bindings/WebRenderAPI.cpp
@@ -260,29 +260,27 @@ WebRenderAPI::GenerateFrame(const nsTArr
 
 void
 WebRenderAPI::SetDisplayList(gfx::Color aBgColor,
                              Epoch aEpoch,
                              mozilla::LayerSize aViewportSize,
                              wr::WrPipelineId pipeline_id,
                              const LayoutSize& content_size,
                              wr::BuiltDisplayListDescriptor dl_descriptor,
-                             uint8_t *dl_data,
-                             size_t dl_size,
+                             wr::Vec_u8& dl_data,
                              ResourceUpdateQueue& aResources)
 {
   wr_api_set_display_list(mDocHandle,
                           ToColorF(aBgColor),
                           aEpoch,
                           aViewportSize.width, aViewportSize.height,
                           pipeline_id,
                           content_size,
                           dl_descriptor,
-                          dl_data,
-                          dl_size,
+                          &dl_data.inner,
                           aResources.Raw());
 }
 
 void
 WebRenderAPI::ClearDisplayList(Epoch aEpoch, wr::WrPipelineId pipeline_id)
 {
   wr_api_clear_display_list(mDocHandle, aEpoch, pipeline_id);
 }
--- a/gfx/webrender_bindings/WebRenderAPI.h
+++ b/gfx/webrender_bindings/WebRenderAPI.h
@@ -156,18 +156,17 @@ public:
   void SetWindowParameters(LayoutDeviceIntSize size);
 
   void SetDisplayList(gfx::Color aBgColor,
                       Epoch aEpoch,
                       mozilla::LayerSize aViewportSize,
                       wr::WrPipelineId pipeline_id,
                       const wr::LayoutSize& content_size,
                       wr::BuiltDisplayListDescriptor dl_descriptor,
-                      uint8_t *dl_data,
-                      size_t dl_size,
+                      wr::Vec_u8& dl_data,
                       ResourceUpdateQueue& aResources);
 
   void ClearDisplayList(Epoch aEpoch, wr::WrPipelineId pipeline_id);
 
   void SetRootPipeline(wr::PipelineId aPipeline);
 
   void RemovePipeline(wr::PipelineId aPipeline);
 
new file mode 100644
--- /dev/null
+++ b/gfx/webrender_bindings/WebRenderTypes.cpp
@@ -0,0 +1,24 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "WebRenderTypes.h"
+
+#include "mozilla/ipc/ByteBuf.h"
+
+namespace mozilla {
+namespace wr {
+
+Vec_u8::Vec_u8(mozilla::ipc::ByteBuf&& aSrc) {
+  inner.data = aSrc.mData;
+  inner.length = aSrc.mLen;
+  inner.capacity = aSrc.mCapacity;
+  aSrc.mData = nullptr;
+  aSrc.mLen = 0;
+  aSrc.mCapacity = 0;
+}
+
+} // namespace wr
+} // namespace mozilla
--- a/gfx/webrender_bindings/WebRenderTypes.h
+++ b/gfx/webrender_bindings/WebRenderTypes.h
@@ -16,16 +16,21 @@
 #include "mozilla/PodOperations.h"
 #include "mozilla/Range.h"
 #include "mozilla/Variant.h"
 #include "Units.h"
 #include "RoundedRect.h"
 #include "nsStyleConsts.h"
 
 namespace mozilla {
+
+namespace ipc {
+class ByteBuf;
+} // namespace ipc
+
 namespace wr {
 
 typedef wr::WrWindowId WindowId;
 typedef wr::WrPipelineId PipelineId;
 typedef wr::WrImageKey ImageKey;
 typedef wr::WrFontKey FontKey;
 typedef wr::WrFontInstanceKey FontInstanceKey;
 typedef wr::WrEpoch Epoch;
@@ -571,16 +576,18 @@ struct Vec_u8 {
     SetEmpty();
   }
   Vec_u8(Vec_u8&) = delete;
   Vec_u8(Vec_u8&& src) {
     inner = src.inner;
     src.SetEmpty();
   }
 
+  explicit Vec_u8(mozilla::ipc::ByteBuf&& aSrc);
+
   Vec_u8&
   operator=(Vec_u8&& src) {
     inner = src.inner;
     src.SetEmpty();
     return *this;
   }
 
   wr::WrVecU8
--- a/gfx/webrender_bindings/moz.build
+++ b/gfx/webrender_bindings/moz.build
@@ -24,16 +24,17 @@ UNIFIED_SOURCES += [
     'Moz2DImageRenderer.cpp',
     'RenderBufferTextureHost.cpp',
     'RendererOGL.cpp',
     'RenderSharedSurfaceTextureHost.cpp',
     'RenderTextureHost.cpp',
     'RenderTextureHostOGL.cpp',
     'RenderThread.cpp',
     'WebRenderAPI.cpp',
+    'WebRenderTypes.cpp',
 ]
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
     EXPORTS.mozilla.webrender += [
         'RenderMacIOSurfaceTextureHostOGL.h',
     ]
     UNIFIED_SOURCES += [
         'RenderMacIOSurfaceTextureHostOGL.cpp',
--- a/gfx/webrender_bindings/src/bindings.rs
+++ b/gfx/webrender_bindings/src/bindings.rs
@@ -953,33 +953,29 @@ pub unsafe extern "C" fn wr_api_set_disp
     dh: &mut DocumentHandle,
     color: ColorF,
     epoch: WrEpoch,
     viewport_width: f32,
     viewport_height: f32,
     pipeline_id: WrPipelineId,
     content_size: LayoutSize,
     dl_descriptor: BuiltDisplayListDescriptor,
-    dl_data: *mut u8,
-    dl_size: usize,
+    dl_data: &mut WrVecU8,
     resources: &mut ResourceUpdates,
 ) {
     let resource_updates = mem::replace(resources, ResourceUpdates::new());
 
     let color = if color.a == 0.0 { None } else { Some(color) };
 
     // See the documentation of set_display_list in api.rs. I don't think
     // it makes a difference in gecko at the moment(until APZ is figured out)
     // but I suppose it is a good default.
     let preserve_frame_state = true;
 
-    let dl_slice = make_slice(dl_data, dl_size);
-    let mut dl_vec = Vec::new();
-    // XXX: see if we can get rid of the copy here
-    dl_vec.extend_from_slice(dl_slice);
+    let dl_vec = dl_data.flush_into_vec();
     let dl = BuiltDisplayList::from_data(dl_vec, dl_descriptor);
 
     dh.api.set_display_list(
         dh.document_id,
         epoch,
         color,
         LayoutSize::new(viewport_width, viewport_height),
         (pipeline_id, content_size, dl),
--- a/gfx/webrender_bindings/webrender_ffi_generated.h
+++ b/gfx/webrender_bindings/webrender_ffi_generated.h
@@ -1063,18 +1063,17 @@ WR_INLINE
 void wr_api_set_display_list(DocumentHandle *aDh,
                              ColorF aColor,
                              WrEpoch aEpoch,
                              float aViewportWidth,
                              float aViewportHeight,
                              WrPipelineId aPipelineId,
                              LayoutSize aContentSize,
                              BuiltDisplayListDescriptor aDlDescriptor,
-                             uint8_t *aDlData,
-                             size_t aDlSize,
+                             WrVecU8 *aDlData,
                              ResourceUpdates *aResources)
 WR_FUNC;
 
 WR_INLINE
 void wr_api_set_root_pipeline(DocumentHandle *aDh,
                               WrPipelineId aPipelineId)
 WR_FUNC;