Skip to content

Commit 17033a9

Browse files
author
bors-servo
authored
Auto merge of #1823 - Gankro:save2, r=kvark
Make save-restore foolproof r? @kvark <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/webrender/1823) <!-- Reviewable:end -->
2 parents a40e1ca + 1bff239 commit 17033a9

File tree

2 files changed

+49
-20
lines changed

2 files changed

+49
-20
lines changed

webrender_api/src/display_list.rs

+36-12
Original file line numberDiff line numberDiff line change
@@ -51,14 +51,6 @@ impl<T> ItemRange<T> {
5151
}
5252
}
5353

54-
#[repr(C)]
55-
#[derive(Debug)]
56-
pub struct DisplayListBuilderSaveState {
57-
dl_len: usize,
58-
clip_stack_len: usize,
59-
next_clip_id: u64,
60-
}
61-
6254
/// A display list.
6355
#[derive(Clone, Default)]
6456
pub struct BuiltDisplayList {
@@ -533,6 +525,13 @@ fn serialize_fast<T: Serialize>(vec: &mut Vec<u8>, e: &T) {
533525
debug_assert!(((w.0 as usize) - (vec.as_ptr() as usize)) == vec.len());
534526
}
535527

528+
#[derive(Clone, Debug)]
529+
pub struct SaveState {
530+
dl_len: usize,
531+
clip_stack_len: usize,
532+
next_clip_id: u64,
533+
}
534+
536535
#[derive(Clone)]
537536
pub struct DisplayListBuilder {
538537
pub data: Vec<u8>,
@@ -544,6 +543,7 @@ pub struct DisplayListBuilder {
544543
/// The size of the content of this display list. This is used to allow scrolling
545544
/// outside the bounds of the display list items themselves.
546545
content_size: LayoutSize,
546+
save_state: Option<SaveState>,
547547
}
548548

549549
impl DisplayListBuilder {
@@ -570,23 +570,41 @@ impl DisplayListBuilder {
570570
next_clip_id: FIRST_CLIP_ID,
571571
builder_start_time: start_time,
572572
content_size,
573+
save_state: None,
573574
}
574575
}
575576

576-
pub fn save(&self) -> DisplayListBuilderSaveState {
577-
DisplayListBuilderSaveState {
577+
/// Saves the current display list state, so it may be `restore()`'d.
578+
///
579+
/// # Conditions:
580+
///
581+
/// * Doesn't support popping clips that were pushed before the save.
582+
/// * Doesn't support nested saves.
583+
/// * Must call `clear_save()` if the restore becomes unnecessary.
584+
pub fn save(&mut self) {
585+
assert!(self.save_state.is_none(), "DisplayListBuilder doesn't support nested saves");
586+
587+
self.save_state = Some(SaveState {
578588
clip_stack_len: self.clip_stack.len(),
579589
dl_len: self.data.len(),
580590
next_clip_id: self.next_clip_id,
581-
}
591+
});
582592
}
583593

584-
pub fn restore(&mut self, state: DisplayListBuilderSaveState) {
594+
/// Restores the state of the builder to when `save()` was last called.
595+
pub fn restore(&mut self) {
596+
let state = self.save_state.take().expect("No save to restore DisplayListBuilder from");
597+
585598
self.clip_stack.truncate(state.clip_stack_len);
586599
self.data.truncate(state.dl_len);
587600
self.next_clip_id = state.next_clip_id;
588601
}
589602

603+
/// Discards the builder's save (indicating the attempted operation was sucessful).
604+
pub fn clear_save(&mut self) {
605+
self.save_state.take().expect("No save to clear in DisplayListBuilder");
606+
}
607+
590608
pub fn print_display_list(&mut self) {
591609
let mut temp = BuiltDisplayList::default();
592610
::std::mem::swap(&mut temp.data, &mut self.data);
@@ -1143,6 +1161,10 @@ impl DisplayListBuilder {
11431161

11441162
pub fn pop_clip_id(&mut self) {
11451163
self.clip_stack.pop();
1164+
if let Some(save_state) = self.save_state.as_ref() {
1165+
assert!(self.clip_stack.len() >= save_state.clip_stack_len,
1166+
"Cannot pop clips that were pushed before the DisplayListBuilder save.");
1167+
}
11461168
assert!(self.clip_stack.len() > 0);
11471169
}
11481170

@@ -1162,6 +1184,8 @@ impl DisplayListBuilder {
11621184
}
11631185

11641186
pub fn finalize(self) -> (PipelineId, LayoutSize, BuiltDisplayList) {
1187+
assert!(self.save_state.is_none(), "Finalized DisplayListBuilder with a pending save");
1188+
11651189
let end_time = precise_time_ns();
11661190

11671191

wrench/src/rawtest.rs

+13-8
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ impl<'a> RawtestHarness<'a> {
216216
ColorF::new(0.0, 0.0, 1.0, 1.0));
217217

218218
if should_try_and_fail {
219-
let save_state = builder.save();
219+
builder.save();
220220
let clip = builder.define_clip(None, rect(80., 80., 90., 90.),
221221
None::<ComplexClipRegion>, None);
222222
builder.push_clip_id(clip);
@@ -231,16 +231,21 @@ impl<'a> RawtestHarness<'a> {
231231
builder.push_line(&PrimitiveInfo::new(rect(100., 100., 100., 100.)),
232232
110., 110., 160., LineOrientation::Horizontal, 2.0,
233233
ColorF::new(0.0, 0.0, 0.0, 1.0), LineStyle::Solid);
234-
builder.restore(save_state);
234+
builder.restore();
235235
}
236236

237-
let clip = builder.define_clip(None, rect(80., 80., 100., 100.),
238-
None::<ComplexClipRegion>, None);
239-
builder.push_clip_id(clip);
240-
builder.push_rect(&PrimitiveInfo::new(rect(150., 150., 100., 100.)),
241-
ColorF::new(0.0, 0.0, 1.0, 1.0));
237+
{
238+
builder.save();
239+
let clip = builder.define_clip(None, rect(80., 80., 100., 100.),
240+
None::<ComplexClipRegion>, None);
241+
builder.push_clip_id(clip);
242+
builder.push_rect(&PrimitiveInfo::new(rect(150., 150., 100., 100.)),
243+
ColorF::new(0.0, 0.0, 1.0, 1.0));
244+
245+
builder.pop_clip_id();
246+
builder.clear_save();
247+
}
242248

243-
builder.pop_clip_id();
244249
builder.pop_clip_id();
245250

246251
self.wrench.api.set_display_list(

0 commit comments

Comments
 (0)