Skip to content

Commit f72bf26

Browse files
committed
Introduce SerializedDisplayItem to reduce mem copies on DL construction
1 parent 586af96 commit f72bf26

File tree

2 files changed

+50
-54
lines changed

2 files changed

+50
-54
lines changed

webrender_api/src/display_item.rs

+9
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,15 @@ pub struct GenericDisplayItem<T> {
6666

6767
pub type DisplayItem = GenericDisplayItem<SpecificDisplayItem>;
6868

69+
/// A modified version of DI where every field is borrowed instead of owned.
70+
/// It allows us to reduce copies during serialization.
71+
#[derive(Serialize)]
72+
pub struct SerializedDisplayItem<'a> {
73+
pub item: &'a SpecificDisplayItem,
74+
pub clip_and_scroll: &'a ClipAndScrollInfo,
75+
pub info: &'a LayoutPrimitiveInfo,
76+
}
77+
6978
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
7079
pub struct PrimitiveInfo<T> {
7180
pub rect: TypedRect<f32, T>,

webrender_api/src/display_list.rs

+41-54
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,9 @@ use {ImageRendering, LayoutPoint, LayoutPrimitiveInfo, LayoutRect, LayoutSideOff
2323
use {LayoutTransform, LayoutVector2D, LineDisplayItem, LineOrientation, LineStyle, MixBlendMode};
2424
use {PipelineId, PropertyBinding, PushReferenceFrameDisplayListItem};
2525
use {PushStackingContextDisplayItem, RadialGradient, RadialGradientDisplayItem};
26-
use {RectangleDisplayItem, ReferenceFrame, ScrollFrameDisplayItem, ScrollSensitivity, Shadow};
27-
use {SpecificDisplayItem, StackingContext, StickyFrameDisplayItem, StickyOffsetBounds};
26+
use {RectangleDisplayItem, ReferenceFrame, ScrollFrameDisplayItem, ScrollSensitivity};
27+
use {SerializedDisplayItem, Shadow, SpecificDisplayItem};
28+
use {StackingContext, StickyFrameDisplayItem, StickyOffsetBounds};
2829
use {TextDisplayItem, TransformStyle, YuvColorSpace, YuvData, YuvImageDisplayItem, ColorDepth};
2930

3031
// We don't want to push a long text-run. If a text-run is too long, split it into several parts.
@@ -691,16 +692,16 @@ impl<'a> Write for SizeCounter {
691692
/// If this assumption is incorrect, the result will be Undefined Behaviour. This
692693
/// assumption should hold for all derived Serialize impls, which is all we currently
693694
/// use.
694-
fn serialize_fast<T: Serialize>(vec: &mut Vec<u8>, e: &T) {
695+
fn serialize_fast<T: Serialize>(vec: &mut Vec<u8>, e: T) {
695696
// manually counting the size is faster than vec.reserve(bincode::serialized_size(&e) as usize) for some reason
696697
let mut size = SizeCounter(0);
697-
bincode::serialize_into(&mut size, e).unwrap();
698+
bincode::serialize_into(&mut size, &e).unwrap();
698699
vec.reserve(size.0);
699700

700701
let old_len = vec.len();
701702
let ptr = unsafe { vec.as_mut_ptr().add(old_len) };
702703
let mut w = UnsafeVecWriter(ptr);
703-
bincode::serialize_into(&mut w, e).unwrap();
704+
bincode::serialize_into(&mut w, &e).unwrap();
704705

705706
// fix up the length
706707
unsafe { vec.set_len(old_len + size.0); }
@@ -964,43 +965,36 @@ impl DisplayListBuilder {
964965
/// NOTE: It is usually preferable to use the specialized methods to push
965966
/// display items. Pushing unexpected or invalid items here may
966967
/// result in WebRender panicking or behaving in unexpected ways.
967-
pub fn push_item(&mut self, item: SpecificDisplayItem, info: &LayoutPrimitiveInfo) {
968+
pub fn push_item(&mut self, item: &SpecificDisplayItem, info: &LayoutPrimitiveInfo) {
968969
serialize_fast(
969970
&mut self.data,
970-
&DisplayItem {
971+
SerializedDisplayItem {
971972
item,
972-
clip_and_scroll: *self.clip_stack.last().unwrap(),
973-
info: *info,
973+
clip_and_scroll: self.clip_stack.last().unwrap(),
974+
info,
974975
},
975976
)
976977
}
977978

978979
fn push_item_with_clip_scroll_info(
979980
&mut self,
980-
item: SpecificDisplayItem,
981+
item: &SpecificDisplayItem,
981982
info: &LayoutPrimitiveInfo,
982-
scrollinfo: ClipAndScrollInfo
983+
clip_and_scroll: &ClipAndScrollInfo
983984
) {
984985
serialize_fast(
985986
&mut self.data,
986-
&DisplayItem {
987+
SerializedDisplayItem {
987988
item,
988-
clip_and_scroll: scrollinfo,
989-
info: *info,
989+
clip_and_scroll,
990+
info,
990991
},
991992
)
992993
}
993994

994-
fn push_new_empty_item(&mut self, item: SpecificDisplayItem, clip_and_scroll: &ClipAndScrollInfo) {
995-
let info = LayoutPrimitiveInfo::new(LayoutRect::zero());
996-
serialize_fast(
997-
&mut self.data,
998-
&DisplayItem {
999-
item,
1000-
clip_and_scroll: *clip_and_scroll,
1001-
info,
1002-
}
1003-
)
995+
fn push_new_empty_item(&mut self, item: &SpecificDisplayItem) {
996+
let info = &LayoutPrimitiveInfo::new(LayoutRect::zero());
997+
self.push_item(item, info)
1004998
}
1005999

10061000
fn push_iter_impl<I>(data: &mut Vec<u8>, iter_source: I)
@@ -1050,11 +1044,11 @@ impl DisplayListBuilder {
10501044

10511045
pub fn push_rect(&mut self, info: &LayoutPrimitiveInfo, color: ColorF) {
10521046
let item = SpecificDisplayItem::Rectangle(RectangleDisplayItem { color });
1053-
self.push_item(item, info);
1047+
self.push_item(&item, info);
10541048
}
10551049

10561050
pub fn push_clear_rect(&mut self, info: &LayoutPrimitiveInfo) {
1057-
self.push_item(SpecificDisplayItem::ClearRectangle, info);
1051+
self.push_item(&SpecificDisplayItem::ClearRectangle, info);
10581052
}
10591053

10601054
pub fn push_line(
@@ -1072,7 +1066,7 @@ impl DisplayListBuilder {
10721066
style,
10731067
});
10741068

1075-
self.push_item(item, info);
1069+
self.push_item(&item, info);
10761070
}
10771071

10781072
pub fn push_image(
@@ -1094,7 +1088,7 @@ impl DisplayListBuilder {
10941088
color,
10951089
});
10961090

1097-
self.push_item(item, info);
1091+
self.push_item(&item, info);
10981092
}
10991093

11001094
/// Push a yuv image. All planar data in yuv image should use the same buffer type.
@@ -1112,7 +1106,7 @@ impl DisplayListBuilder {
11121106
color_space,
11131107
image_rendering,
11141108
});
1115-
self.push_item(item, info);
1109+
self.push_item(&item, info);
11161110
}
11171111

11181112
pub fn push_text(
@@ -1130,7 +1124,7 @@ impl DisplayListBuilder {
11301124
});
11311125

11321126
for split_glyphs in glyphs.chunks(MAX_TEXT_RUN_LENGTH) {
1133-
self.push_item(item, info);
1127+
self.push_item(&item, info);
11341128
self.push_iter(split_glyphs);
11351129
}
11361130
}
@@ -1173,7 +1167,7 @@ impl DisplayListBuilder {
11731167
) {
11741168
let item = SpecificDisplayItem::Border(BorderDisplayItem { details, widths });
11751169

1176-
self.push_item(item, info);
1170+
self.push_item(&item, info);
11771171
}
11781172

11791173
pub fn push_box_shadow(
@@ -1197,7 +1191,7 @@ impl DisplayListBuilder {
11971191
clip_mode,
11981192
});
11991193

1200-
self.push_item(item, info);
1194+
self.push_item(&item, info);
12011195
}
12021196

12031197
/// Pushes a linear gradient to be displayed.
@@ -1227,7 +1221,7 @@ impl DisplayListBuilder {
12271221
tile_spacing,
12281222
});
12291223

1230-
self.push_item(item, info);
1224+
self.push_item(&item, info);
12311225
}
12321226

12331227
/// Pushes a radial gradient to be displayed.
@@ -1246,7 +1240,7 @@ impl DisplayListBuilder {
12461240
tile_spacing,
12471241
});
12481242

1249-
self.push_item(item, info);
1243+
self.push_item(&item, info);
12501244
}
12511245

12521246
pub fn push_reference_frame(
@@ -1263,13 +1257,12 @@ impl DisplayListBuilder {
12631257
id,
12641258
},
12651259
});
1266-
self.push_item(item, info);
1260+
self.push_item(&item, info);
12671261
id
12681262
}
12691263

12701264
pub fn pop_reference_frame(&mut self) {
1271-
let clip_and_scroll = *self.clip_stack.last().unwrap();
1272-
self.push_new_empty_item(SpecificDisplayItem::PopReferenceFrame, &clip_and_scroll);
1265+
self.push_new_empty_item(&SpecificDisplayItem::PopReferenceFrame);
12731266
}
12741267

12751268
pub fn push_stacking_context(
@@ -1290,21 +1283,19 @@ impl DisplayListBuilder {
12901283
},
12911284
});
12921285

1293-
self.push_item(item, info);
1286+
self.push_item(&item, info);
12941287
self.push_iter(filters);
12951288
}
12961289

12971290
pub fn pop_stacking_context(&mut self) {
1298-
let clip_and_scroll = *self.clip_stack.last().unwrap();
1299-
self.push_new_empty_item(SpecificDisplayItem::PopStackingContext, &clip_and_scroll);
1291+
self.push_new_empty_item(&SpecificDisplayItem::PopStackingContext);
13001292
}
13011293

13021294
pub fn push_stops(&mut self, stops: &[GradientStop]) {
13031295
if stops.is_empty() {
13041296
return;
13051297
}
1306-
let clip_and_scroll = *self.clip_stack.last().unwrap();
1307-
self.push_new_empty_item(SpecificDisplayItem::SetGradientStops, &clip_and_scroll);
1298+
self.push_new_empty_item(&SpecificDisplayItem::SetGradientStops);
13081299
self.push_iter(stops);
13091300
}
13101301

@@ -1372,9 +1363,9 @@ impl DisplayListBuilder {
13721363
});
13731364

13741365
self.push_item_with_clip_scroll_info(
1375-
item,
1366+
&item,
13761367
&LayoutPrimitiveInfo::with_clip_rect(content_rect, clip_rect),
1377-
ClipAndScrollInfo::simple(parent),
1368+
&ClipAndScrollInfo::simple(parent),
13781369
);
13791370
self.push_iter(complex_clips);
13801371

@@ -1391,8 +1382,7 @@ impl DisplayListBuilder {
13911382
I::IntoIter: ExactSizeIterator + Clone,
13921383
{
13931384
let id = self.generate_clip_chain_id();
1394-
let clip_and_scroll = *self.clip_stack.last().unwrap();
1395-
self.push_new_empty_item(SpecificDisplayItem::ClipChain(ClipChainItem { id, parent }), &clip_and_scroll);
1385+
self.push_new_empty_item(&SpecificDisplayItem::ClipChain(ClipChainItem { id, parent }));
13961386
self.push_iter(clips);
13971387
id
13981388
}
@@ -1454,7 +1444,7 @@ impl DisplayListBuilder {
14541444

14551445
let info = LayoutPrimitiveInfo::new(clip_rect);
14561446

1457-
self.push_item_with_clip_scroll_info(item, &info, scrollinfo);
1447+
self.push_item_with_clip_scroll_info(&item, &info, &scrollinfo);
14581448
self.push_iter(complex_clips);
14591449
id
14601450
}
@@ -1477,7 +1467,7 @@ impl DisplayListBuilder {
14771467
});
14781468

14791469
let info = LayoutPrimitiveInfo::new(frame_rect);
1480-
self.push_item(item, &info);
1470+
self.push_item(&item, &info);
14811471
id
14821472
}
14831473

@@ -1509,24 +1499,21 @@ impl DisplayListBuilder {
15091499
pipeline_id,
15101500
ignore_missing_pipeline,
15111501
});
1512-
self.push_item(item, info);
1502+
self.push_item(&item, info);
15131503
}
15141504

15151505
pub fn push_shadow(&mut self, info: &LayoutPrimitiveInfo, shadow: Shadow) {
1516-
self.push_item(SpecificDisplayItem::PushShadow(shadow), info);
1506+
self.push_item(&SpecificDisplayItem::PushShadow(shadow), info);
15171507
}
15181508

15191509
pub fn pop_all_shadows(&mut self) {
1520-
let clip_and_scroll = *self.clip_stack.last().unwrap();
1521-
self.push_new_empty_item(SpecificDisplayItem::PopAllShadows, &clip_and_scroll);
1510+
self.push_new_empty_item(&SpecificDisplayItem::PopAllShadows);
15221511
}
15231512

15241513
pub fn finalize(self) -> (PipelineId, LayoutSize, BuiltDisplayList) {
15251514
assert!(self.save_state.is_none(), "Finalized DisplayListBuilder with a pending save");
15261515

15271516
let end_time = precise_time_ns();
1528-
1529-
15301517
(
15311518
self.pipeline_id,
15321519
self.content_size,

0 commit comments

Comments
 (0)