Bug 1342558. Change SetRootDisplayList to consume built display lists. r=nical
authorJeff Muizelaar <jmuizelaar@mozilla.com>
Wed, 01 Mar 2017 09:10:53 -0500
changeset 345876 7d88bb71fefb36157f16769e87658a39248a2a91
parent 345875 e306b40ff823a65433b153cd0ab85f720ab05e02
child 345877 9059ef02d91ba49bb3cf3b9cdd4c92bc99a4d4b0
push id38337
push userkwierso@gmail.com
push dateSat, 04 Mar 2017 01:30:14 +0000
treeherderautoland@b691557cb7a3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnical
bugs1342558
milestone54.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 1342558. Change SetRootDisplayList to consume built display lists. r=nical
gfx/layers/wr/WebRenderBridgeParent.cpp
gfx/webrender_bindings/WebRenderAPI.cpp
gfx/webrender_bindings/WebRenderAPI.h
gfx/webrender_bindings/WebRenderTypes.h
gfx/webrender_bindings/src/bindings.rs
gfx/webrender_bindings/webrender_ffi.h
--- a/gfx/layers/wr/WebRenderBridgeParent.cpp
+++ b/gfx/layers/wr/WebRenderBridgeParent.cpp
@@ -399,17 +399,25 @@ WebRenderBridgeParent::ProcessWebrenderC
                               op.clip_mode());
         break;
       }
       default:
         NS_RUNTIMEABORT("not reached");
     }
   }
   builder.End();
-  mApi->SetRootDisplayList(gfx::Color(0.3f, 0.f, 0.f, 1.f), aEpoch, LayerSize(aSize.width, aSize.height), builder);
+  WrBuiltDisplayListDescriptor dlDesc;
+  wr::VecU8 dlData;
+  WrAuxiliaryListsDescriptor auxDesc;
+  wr::VecU8 auxData;
+  builder.Finalize(dlDesc, dlData, auxDesc, auxData);
+  mApi->SetRootDisplayList(gfx::Color(0.3f, 0.f, 0.f, 1.f), aEpoch, LayerSize(aSize.width, aSize.height),
+                           mPipelineId,
+                           dlDesc, dlData.inner.data, dlData.inner.length,
+                           auxDesc, auxData.inner.data, auxData.inner.length);
 
   ScheduleComposition();
   DeleteOldImages();
 
   // XXX remove it when external image key is used.
   if (!keysToDelete.empty()) {
     mKeysToDelete.swap(keysToDelete);
   }
--- a/gfx/webrender_bindings/WebRenderAPI.cpp
+++ b/gfx/webrender_bindings/WebRenderAPI.cpp
@@ -159,21 +159,34 @@ WebRenderAPI::GenerateFrame()
 {
   wr_api_generate_frame(mWrApi);
 }
 
 void
 WebRenderAPI::SetRootDisplayList(gfx::Color aBgColor,
                                  Epoch aEpoch,
                                  LayerSize aViewportSize,
-                                 DisplayListBuilder& aBuilder)
+				 WrPipelineId pipeline_id,
+				 WrBuiltDisplayListDescriptor dl_descriptor,
+				 uint8_t *dl_data,
+				 size_t dl_size,
+				 WrAuxiliaryListsDescriptor aux_descriptor,
+				 uint8_t *aux_data,
+				 size_t aux_size)
 {
-  wr_api_set_root_display_list(mWrApi, aBuilder.mWrState,
-                               aEpoch,
-                               aViewportSize.width, aViewportSize.height);
+    wr_api_set_root_display_list(mWrApi,
+				 aEpoch,
+				 aViewportSize.width, aViewportSize.height,
+                                 pipeline_id,
+                                 dl_descriptor,
+                                 dl_data,
+                                 dl_size,
+                                 aux_descriptor,
+                                 aux_data,
+                                 aux_size);
 }
 
 void
 WebRenderAPI::Readback(gfx::IntSize size,
                        uint8_t *buffer,
                        uint32_t buffer_size)
 {
     class Readback : public RendererEvent
@@ -334,16 +347,29 @@ DisplayListBuilder::Begin(const LayerInt
 
 void
 DisplayListBuilder::End()
 {
   wr_dp_end(mWrState);
 }
 
 void
+DisplayListBuilder::Finalize(WrBuiltDisplayListDescriptor& dl_descriptor,
+                             wr::VecU8& dl_data,
+                             WrAuxiliaryListsDescriptor& aux_descriptor,
+                             wr::VecU8& aux_data)
+{
+    wr_api_finalize_builder(mWrState,
+                            dl_descriptor,
+                            dl_data.inner,
+                            aux_descriptor,
+                            aux_data.inner);
+}
+
+void
 DisplayListBuilder::PushStackingContext(const WrRect& aBounds,
                                         const WrRect& aOverflow,
                                         const WrImageMask* aMask,
                                         const float aOpacity,
                                         const gfx::Matrix4x4& aTransform,
                                         const WrMixBlendMode& aMixBlendMode)
 {
   wr_dp_push_stacking_context(mWrState, aBounds, aOverflow, aMask, aOpacity,
--- a/gfx/webrender_bindings/WebRenderAPI.h
+++ b/gfx/webrender_bindings/WebRenderAPI.h
@@ -24,34 +24,42 @@ class CompositorBridgeParentBase;
 }
 
 namespace wr {
 
 class DisplayListBuilder;
 class RendererOGL;
 class RendererEvent;
 
+
+
 class WebRenderAPI
 {
   NS_INLINE_DECL_REFCOUNTING(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,
+                          Epoch aEpoch,
                           LayerSize aViewportSize,
-                          DisplayListBuilder& aBuilder);
+                          WrPipelineId pipeline_id,
+                          WrBuiltDisplayListDescriptor dl_descriptor,
+                          uint8_t *dl_data,
+                          size_t dl_size,
+                          WrAuxiliaryListsDescriptor aux_descriptor,
+                          uint8_t *aux_data,
+                          size_t aux_size);
 
   void SetRootPipeline(wr::PipelineId aPipeline);
 
   void AddImage(wr::ImageKey aKey,
                 const ImageDescriptor& aDescriptor,
                 Range<uint8_t> aBytes);
 
   wr::ImageKey AddExternalImageHandle(gfx::IntSize aSize,
@@ -103,16 +111,20 @@ public:
   explicit DisplayListBuilder(wr::PipelineId aId);
   DisplayListBuilder(DisplayListBuilder&&) = default;
 
   ~DisplayListBuilder();
 
   void Begin(const LayerIntSize& aSize);
 
   void End();
+  void Finalize(WrBuiltDisplayListDescriptor& dl_descriptor,
+                wr::VecU8& dl_data,
+                WrAuxiliaryListsDescriptor& aux_descriptor,
+                wr::VecU8& aux_data);
 
   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/WebRenderTypes.h
+++ b/gfx/webrender_bindings/WebRenderTypes.h
@@ -288,12 +288,29 @@ struct ByteBuffer
           !(memcmp(mData, other.mData, mLength));
   }
 
   size_t mLength;
   uint8_t* mData;
   bool mOwned;
 };
 
+struct VecU8 {
+  WrVecU8 inner;
+  VecU8() {
+    inner.data = nullptr;
+  }
+  VecU8(VecU8&) = delete;
+  VecU8(VecU8&& src) {
+    inner = src.inner;
+    src.inner.data = nullptr;
+  }
+
+  ~VecU8() {
+    if (inner.data)
+      wr_vec_u8_free(inner);
+  }
+};
+
 } // namespace wr
 } // namespace mozilla
 
 #endif /* GFX_WEBRENDERTYPES_H */
--- a/gfx/webrender_bindings/src/bindings.rs
+++ b/gfx/webrender_bindings/src/bindings.rs
@@ -6,16 +6,18 @@ use gleam::gl;
 use webrender_traits::{BorderSide, BorderStyle, BorderRadius, BorderWidths, BorderDetails, NormalBorder};
 use webrender_traits::{PipelineId, ClipRegion, PropertyBinding};
 use webrender_traits::{Epoch, ExtendMode, ColorF, GlyphInstance, GradientStop, ImageDescriptor};
 use webrender_traits::{FilterOp, ImageData, ImageFormat, ImageKey, ImageMask, ImageRendering, RendererKind, MixBlendMode};
 use webrender_traits::{ExternalImageId, RenderApi, FontKey};
 use webrender_traits::{DeviceUintSize, ExternalEvent};
 use webrender_traits::{LayoutPoint, LayoutRect, LayoutSize, LayoutTransform};
 use webrender_traits::{BoxShadowClipMode, LayerPixel, ServoScrollRootId, IdNamespace};
+use webrender_traits::{BuiltDisplayListDescriptor, AuxiliaryListsDescriptor};
+use webrender_traits::{BuiltDisplayList, AuxiliaryLists};
 use webrender::renderer::{Renderer, RendererOptions};
 use webrender::renderer::{ExternalImage, ExternalImageHandler, ExternalImageSource};
 use webrender::{ApiRecordingReceiver, BinaryRecorder};
 use app_units::Au;
 use euclid::TypedPoint2D;
 
 extern crate webrender_traits;
 
@@ -72,16 +74,39 @@ impl WrImageDescriptor {
             stride: if self.stride != 0 { Some(self.stride) } else { None },
             format: self.format,
             is_opaque: self.is_opaque,
             offset: 0,
         }
     }
 }
 
+#[repr(C)]
+pub struct WrVecU8 {
+    ptr: *mut u8,
+    length: usize,
+    capacity: usize
+}
+
+impl WrVecU8 {
+    fn to_vec(self) -> Vec<u8> {
+        unsafe { Vec::from_raw_parts(self.ptr, self.length, self.capacity) }
+    }
+    fn from_vec(mut v: Vec<u8>) -> WrVecU8 {
+        let w = WrVecU8{ptr: v.as_mut_ptr(), length: v.len(), capacity: v.capacity()};
+        mem::forget(v);
+        w
+    }
+}
+
+#[no_mangle]
+pub extern fn wr_vec_u8_free(v: WrVecU8) {
+    v.to_vec();
+}
+
 fn get_proc_address(glcontext_ptr: *mut c_void, name: &str) -> *const c_void{
 
     extern  {
         fn get_proc_address_from_glcontext(glcontext_ptr: *mut c_void, procname: *const c_char) -> *const c_void;
     }
 
     let symbol_name = CString::new(name).unwrap();
     let symbol = unsafe {
@@ -174,33 +199,70 @@ pub unsafe extern fn wr_api_get_namespac
 
 #[no_mangle]
 pub unsafe extern fn wr_api_delete(api: *mut RenderApi) {
     let api = Box::from_raw(api);
     api.shut_down();
 }
 
 #[no_mangle]
+pub unsafe extern fn wr_api_finalize_builder(state: &mut WrState,
+                                             dl_descriptor: &mut BuiltDisplayListDescriptor,
+                                             dl_data: &mut WrVecU8,
+                                             aux_descriptor: &mut AuxiliaryListsDescriptor,
+                                             aux_data: &mut WrVecU8)
+{
+    let frame_builder = mem::replace(&mut state.frame_builder,
+                                     WebRenderFrameBuilder::new(state.pipeline_id));
+    let (pipeline_id, dl, aux) = frame_builder.dl_builder.finalize();
+    //XXX: get rid of the copies here
+    *dl_data = WrVecU8::from_vec(dl.data().to_owned());
+    *dl_descriptor = dl.descriptor().clone();
+    *aux_data = WrVecU8::from_vec(aux.data().to_owned());
+    *aux_descriptor = aux.descriptor().clone();
+}
+
+#[no_mangle]
 pub unsafe extern fn wr_api_set_root_display_list(api: &mut RenderApi,
-                                                  state: &mut WrState,
                                                   epoch: Epoch,
                                                   viewport_width: f32,
-                                                  viewport_height: f32) {
+                                                  viewport_height: f32,
+                                                  pipeline_id: PipelineId,
+                                                  dl_descriptor: BuiltDisplayListDescriptor,
+                                                  dl_data: *mut u8,
+                                                  dl_size: usize,
+                                                  aux_descriptor: AuxiliaryListsDescriptor,
+                                                  aux_data: *mut u8,
+                                                  aux_size: usize) {
     let root_background_color = ColorF::new(0.3, 0.0, 0.0, 1.0);
-    let frame_builder = mem::replace(&mut state.frame_builder,
-                                     WebRenderFrameBuilder::new(state.pipeline_id));
     // See the documentation of set_root_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_builder, aux_builder) = fb.dl_builder.finalize();
+
+    let dl_slice = unsafe {
+        slice::from_raw_parts(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 = BuiltDisplayList::from_data(dl_vec, dl_descriptor);
+
+    let aux_slice = unsafe {
+        slice::from_raw_parts(aux_data, aux_size)
+    };
+    let mut aux_vec = Vec::new();
+    // XXX: see if we can get rid of the copy here
+    aux_vec.extend_from_slice(aux_slice);
+    let aux = AuxiliaryLists::from_data(aux_vec, aux_descriptor);
+
     api.set_root_display_list(Some(root_background_color),
                               epoch,
                               LayoutSize::new(viewport_width, viewport_height),
-                              frame_builder.dl_builder.finalize(),
+                              (pipeline_id, dl, aux),
                               preserve_frame_state);
 }
 
 #[no_mangle]
 pub extern fn wr_api_generate_frame(api: &mut RenderApi) {
   api.generate_frame(None);
 }
 
--- a/gfx/webrender_bindings/webrender_ffi.h
+++ b/gfx/webrender_bindings/webrender_ffi.h
@@ -336,16 +336,33 @@ struct WrExternalImageHandler
 struct WrImageDescriptor {
     WrImageFormat format;
     uint32_t width;
     uint32_t height;
     uint32_t stride;
     bool is_opaque;
 };
 
+struct WrBuiltDisplayListDescriptor {
+    size_t display_list_items_size;
+};
+
+struct WrAuxiliaryListsDescriptor {
+    size_t gradient_stops_size;
+    size_t complex_clip_regions_size;
+    size_t filters_size;
+    size_t glyph_instances_size;
+};
+
+struct WrVecU8 {
+    uint8_t *data;
+    size_t length;
+    size_t capacity;
+};
+
 // -----
 // Functions exposed by the webrender API
 // -----
 
 // Some useful defines to stub out webrender binding functions for when we
 // build gecko without webrender. We try to tell the compiler these functions
 // are unreachable in that case, but VC++ emits a warning if it finds any
 // unreachable functions invoked from destructors. That warning gets turned into
@@ -442,17 +459,24 @@ WR_INLINE void
 wr_api_delete_image(WrAPI* api, WrImageKey key)
 WR_FUNC;
 
 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_api_set_root_display_list(WrAPI* api, WrEpoch epoch, float w, float h,
+                             WrPipelineId pipeline_id,
+                             WrBuiltDisplayListDescriptor dl_descriptor,
+                             uint8_t *dl_data,
+                             size_t dl_size,
+                             WrAuxiliaryListsDescriptor aux_descriptor,
+                             uint8_t *aux_data,
+                             size_t aux_size)
 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)
@@ -554,13 +578,25 @@ wr_dp_push_box_shadow(WrState* wrState, 
                       float blur_radius, float spread_radius, float border_radius,
                       WrBoxShadowClipMode clip_mode)
 WR_FUNC;
 
 WR_INLINE WrIdNamespace
 wr_api_get_namespace(WrAPI* api)
 WR_FUNC;
 
+WR_INLINE void
+wr_api_finalize_builder(WrState* wrState,
+                        WrBuiltDisplayListDescriptor& dl_descriptor,
+                        WrVecU8& dl_data,
+                        WrAuxiliaryListsDescriptor& aux_descriptor,
+                        WrVecU8& aux_data)
+WR_FUNC;
+
+WR_INLINE void
+wr_vec_u8_free(WrVecU8 dl_data)
+WR_FUNC;
+
 #undef WR_FUNC
 #undef WR_DESTRUCTOR_SAFE_FUNC
 } // extern "C"
 
 #endif // WR_h