1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this
3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4 
5 use euclid::SideOffsets2D;
6 use peek_poke::{ensure_red_zone, peek_from_slice, poke_extend_vec, strip_red_zone};
7 use peek_poke::{poke_inplace_slice, poke_into_vec, Poke};
8 #[cfg(feature = "deserialize")]
9 use serde::de::Deserializer;
10 #[cfg(feature = "serialize")]
11 use serde::ser::{Serializer, SerializeSeq};
12 use serde::{Deserialize, Serialize};
13 use std::io::Write;
14 use std::marker::PhantomData;
15 use std::ops::Range;
16 use std::mem;
17 use std::collections::HashMap;
18 use time::precise_time_ns;
19 use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
20 // local imports
21 use crate::display_item as di;
22 use crate::display_item_cache::*;
23 use crate::{PipelineId, PropertyBinding};
24 use crate::gradient_builder::GradientBuilder;
25 use crate::color::ColorF;
26 use crate::font::{FontInstanceKey, GlyphInstance, GlyphOptions};
27 use crate::image::{ColorDepth, ImageKey};
28 use crate::units::*;
29 
30 
31 // We don't want to push a long text-run. If a text-run is too long, split it into several parts.
32 // This needs to be set to (renderer::MAX_VERTEX_TEXTURE_WIDTH - VECS_PER_TEXT_RUN) * 2
33 pub const MAX_TEXT_RUN_LENGTH: usize = 2040;
34 
35 // See ROOT_REFERENCE_FRAME_SPATIAL_ID and ROOT_SCROLL_NODE_SPATIAL_ID
36 // TODO(mrobinson): It would be a good idea to eliminate the root scroll frame which is only
37 // used by Servo.
38 const FIRST_SPATIAL_NODE_INDEX: usize = 2;
39 
40 // See ROOT_SCROLL_NODE_SPATIAL_ID
41 const FIRST_CLIP_NODE_INDEX: usize = 1;
42 
43 #[repr(C)]
44 #[derive(Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
45 pub struct ItemRange<'a, T> {
46     bytes: &'a [u8],
47     _boo: PhantomData<T>,
48 }
49 
50 impl<'a, T> Copy for ItemRange<'a, T> {}
51 impl<'a, T> Clone for ItemRange<'a, T> {
clone(&self) -> Self52     fn clone(&self) -> Self {
53         *self
54     }
55 }
56 
57 impl<'a, T> Default for ItemRange<'a, T> {
default() -> Self58     fn default() -> Self {
59         ItemRange {
60             bytes: Default::default(),
61             _boo: PhantomData,
62         }
63     }
64 }
65 
66 impl<'a, T> ItemRange<'a, T> {
new(bytes: &'a [u8]) -> Self67     pub fn new(bytes: &'a [u8]) -> Self {
68         Self {
69             bytes,
70             _boo: PhantomData
71         }
72     }
73 
is_empty(&self) -> bool74     pub fn is_empty(&self) -> bool {
75         // Nothing more than space for a length (0).
76         self.bytes.len() <= mem::size_of::<usize>()
77     }
78 
bytes(&self) -> &[u8]79     pub fn bytes(&self) -> &[u8] {
80         &self.bytes
81     }
82 }
83 
84 impl<'a, T: Default> ItemRange<'a, T> {
iter(&self) -> AuxIter<'a, T>85     pub fn iter(&self) -> AuxIter<'a, T> {
86         AuxIter::new(T::default(), self.bytes)
87     }
88 }
89 
90 impl<'a, T> IntoIterator for ItemRange<'a, T>
91 where
92     T: Copy + Default + peek_poke::Peek,
93 {
94     type Item = T;
95     type IntoIter = AuxIter<'a, T>;
into_iter(self) -> Self::IntoIter96     fn into_iter(self) -> Self::IntoIter {
97         self.iter()
98     }
99 }
100 
101 #[derive(Copy, Clone)]
102 pub struct TempFilterData<'a> {
103     pub func_types: ItemRange<'a, di::ComponentTransferFuncType>,
104     pub r_values: ItemRange<'a, f32>,
105     pub g_values: ItemRange<'a, f32>,
106     pub b_values: ItemRange<'a, f32>,
107     pub a_values: ItemRange<'a, f32>,
108 }
109 
110 /// A display list.
111 #[derive(Clone, Default)]
112 pub struct BuiltDisplayList {
113     /// Serde encoded bytes. Mostly DisplayItems, but some mixed in slices.
114     data: Vec<u8>,
115     descriptor: BuiltDisplayListDescriptor,
116 }
117 
118 #[repr(C)]
119 #[derive(Copy, Clone, Deserialize, Serialize)]
120 pub enum GeckoDisplayListType {
121   None,
122   Partial(f64),
123   Full(f64),
124 }
125 
126 impl Default for GeckoDisplayListType {
default() -> Self127   fn default() -> Self { GeckoDisplayListType::None }
128 }
129 
130 /// Describes the memory layout of a display list.
131 ///
132 /// A display list consists of some number of display list items, followed by a number of display
133 /// items.
134 #[repr(C)]
135 #[derive(Copy, Clone, Default, Deserialize, Serialize)]
136 pub struct BuiltDisplayListDescriptor {
137     /// Gecko specific information about the display list.
138     gecko_display_list_type: GeckoDisplayListType,
139     /// The first IPC time stamp: before any work has been done
140     builder_start_time: u64,
141     /// The second IPC time stamp: after serialization
142     builder_finish_time: u64,
143     /// The third IPC time stamp: just before sending
144     send_start_time: u64,
145     /// The amount of clipping nodes created while building this display list.
146     total_clip_nodes: usize,
147     /// The amount of spatial nodes created while building this display list.
148     total_spatial_nodes: usize,
149     /// The size of the cache for this display list.
150     cache_size: usize,
151     /// The offset for additional display list data.
152     extra_data_offset: usize,
153 }
154 
155 #[derive(Clone)]
156 pub struct DisplayListWithCache {
157     display_list: BuiltDisplayList,
158     cache: DisplayItemCache,
159 }
160 
161 impl DisplayListWithCache {
iter(&self) -> BuiltDisplayListIter162     pub fn iter(&self) -> BuiltDisplayListIter {
163         self.display_list.iter_with_cache(&self.cache)
164     }
165 
new_from_list(display_list: BuiltDisplayList) -> Self166     pub fn new_from_list(display_list: BuiltDisplayList) -> Self {
167         let mut cache = DisplayItemCache::new();
168         cache.update(&display_list);
169 
170         DisplayListWithCache {
171             display_list,
172             cache
173         }
174     }
175 
update(&mut self, display_list: BuiltDisplayList)176     pub fn update(&mut self, display_list: BuiltDisplayList) {
177         self.cache.update(&display_list);
178         self.display_list = display_list;
179     }
180 
descriptor(&self) -> &BuiltDisplayListDescriptor181     pub fn descriptor(&self) -> &BuiltDisplayListDescriptor {
182         self.display_list.descriptor()
183     }
184 
times(&self) -> (u64, u64, u64)185     pub fn times(&self) -> (u64, u64, u64) {
186         self.display_list.times()
187     }
188 
data(&self) -> &[u8]189     pub fn data(&self) -> &[u8] {
190         self.display_list.data()
191     }
192 }
193 
194 impl MallocSizeOf for DisplayListWithCache {
size_of(&self, ops: &mut MallocSizeOfOps) -> usize195     fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
196         self.display_list.data.size_of(ops) + self.cache.size_of(ops)
197     }
198 }
199 
200 #[cfg(feature = "serialize")]
201 impl Serialize for DisplayListWithCache {
serialize<S: Serializer>( &self, serializer: S ) -> Result<S::Ok, S::Error>202     fn serialize<S: Serializer>(
203         &self,
204         serializer: S
205     ) -> Result<S::Ok, S::Error> {
206         BuiltDisplayList::serialize_with_iterator(serializer, self.iter())
207     }
208 }
209 
210 #[cfg(feature = "deserialize")]
211 impl<'de> Deserialize<'de> for DisplayListWithCache {
deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'de>,212     fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
213     where
214         D: Deserializer<'de>,
215     {
216         let display_list = BuiltDisplayList::deserialize(deserializer)?;
217         let cache = DisplayItemCache::new();
218 
219         Ok(DisplayListWithCache {
220             display_list,
221             cache,
222         })
223     }
224 }
225 
226 impl BuiltDisplayListDescriptor {}
227 
228 pub struct BuiltDisplayListIter<'a> {
229     list: &'a BuiltDisplayList,
230     data: &'a [u8],
231     cache: Option<&'a DisplayItemCache>,
232     pending_items: std::slice::Iter<'a, CachedDisplayItem>,
233     cur_cached_item: Option<&'a CachedDisplayItem>,
234     cur_item: di::DisplayItem,
235     cur_stops: ItemRange<'a, di::GradientStop>,
236     cur_glyphs: ItemRange<'a, GlyphInstance>,
237     cur_filters: ItemRange<'a, di::FilterOp>,
238     cur_filter_data: Vec<TempFilterData<'a>>,
239     cur_filter_primitives: ItemRange<'a, di::FilterPrimitive>,
240     cur_clip_chain_items: ItemRange<'a, di::ClipId>,
241     cur_points: ItemRange<'a, LayoutPoint>,
242     peeking: Peek,
243     /// Should just be initialized but never populated in release builds
244     debug_stats: DebugStats,
245 }
246 
247 /// Internal info used for more detailed analysis of serialized display lists
248 #[allow(dead_code)]
249 struct DebugStats {
250     /// Last address in the buffer we pointed to, for computing serialized sizes
251     last_addr: usize,
252     stats: HashMap<&'static str, ItemStats>,
253 }
254 
255 impl DebugStats {
256     #[cfg(feature = "display_list_stats")]
_update_entry(&mut self, name: &'static str, item_count: usize, byte_count: usize)257     fn _update_entry(&mut self, name: &'static str, item_count: usize, byte_count: usize) {
258         let entry = self.stats.entry(name).or_default();
259         entry.total_count += item_count;
260         entry.num_bytes += byte_count;
261     }
262 
263     /// Computes the number of bytes we've processed since we last called
264     /// this method, so we can compute the serialized size of a display item.
265     #[cfg(feature = "display_list_stats")]
debug_num_bytes(&mut self, data: &[u8]) -> usize266     fn debug_num_bytes(&mut self, data: &[u8]) -> usize {
267         let old_addr = self.last_addr;
268         let new_addr = data.as_ptr() as usize;
269         let delta = new_addr - old_addr;
270         self.last_addr = new_addr;
271 
272         delta
273     }
274 
275     /// Logs stats for the last deserialized display item
276     #[cfg(feature = "display_list_stats")]
log_item(&mut self, data: &[u8], item: &di::DisplayItem)277     fn log_item(&mut self, data: &[u8], item: &di::DisplayItem) {
278         let num_bytes = self.debug_num_bytes(data);
279         self._update_entry(item.debug_name(), 1, num_bytes);
280     }
281 
282     /// Logs the stats for the given serialized slice
283     #[cfg(feature = "display_list_stats")]
log_slice<T: Copy + Default + peek_poke::Peek>( &mut self, slice_name: &'static str, range: &ItemRange<T>, )284     fn log_slice<T: Copy + Default + peek_poke::Peek>(
285         &mut self,
286         slice_name: &'static str,
287         range: &ItemRange<T>,
288     ) {
289         // Run this so log_item_stats is accurate, but ignore its result
290         // because log_slice_stats may be called after multiple slices have been
291         // processed, and the `range` has everything we need.
292         self.last_addr = range.bytes.as_ptr() as usize + range.bytes.len();
293 
294         self._update_entry(slice_name, range.iter().len(), range.bytes.len());
295     }
296 
297     #[cfg(not(feature = "display_list_stats"))]
log_slice<T>(&mut self, _slice_name: &str, _range: &ItemRange<T>)298     fn log_slice<T>(&mut self, _slice_name: &str, _range: &ItemRange<T>) {
299         /* no-op */
300     }
301 }
302 
303 /// Stats for an individual item
304 #[derive(Copy, Clone, Debug, Default)]
305 pub struct ItemStats {
306     /// How many instances of this kind of item we deserialized
307     pub total_count: usize,
308     /// How many bytes we processed for this kind of item
309     pub num_bytes: usize,
310 }
311 
312 pub struct DisplayItemRef<'a: 'b, 'b> {
313     iter: &'b BuiltDisplayListIter<'a>,
314 }
315 
316 // Some of these might just become ItemRanges
317 impl<'a, 'b> DisplayItemRef<'a, 'b> {
display_list(&self) -> &BuiltDisplayList318     pub fn display_list(&self) -> &BuiltDisplayList {
319         self.iter.display_list()
320     }
321 
322     // Creates a new iterator where this element's iterator is, to hack around borrowck.
sub_iter(&self) -> BuiltDisplayListIter<'a>323     pub fn sub_iter(&self) -> BuiltDisplayListIter<'a> {
324         self.iter.sub_iter()
325     }
326 
item(&self) -> &di::DisplayItem327     pub fn item(&self) -> &di::DisplayItem {
328        self.iter.current_item()
329     }
330 
clip_chain_items(&self) -> ItemRange<di::ClipId>331     pub fn clip_chain_items(&self) -> ItemRange<di::ClipId> {
332         self.iter.cur_clip_chain_items
333     }
334 
points(&self) -> ItemRange<LayoutPoint>335     pub fn points(&self) -> ItemRange<LayoutPoint> {
336         self.iter.cur_points
337     }
338 
glyphs(&self) -> ItemRange<GlyphInstance>339     pub fn glyphs(&self) -> ItemRange<GlyphInstance> {
340         self.iter.glyphs()
341     }
342 
gradient_stops(&self) -> ItemRange<di::GradientStop>343     pub fn gradient_stops(&self) -> ItemRange<di::GradientStop> {
344         self.iter.gradient_stops()
345     }
346 
filters(&self) -> ItemRange<di::FilterOp>347     pub fn filters(&self) -> ItemRange<di::FilterOp> {
348         self.iter.cur_filters
349     }
350 
filter_datas(&self) -> &Vec<TempFilterData>351     pub fn filter_datas(&self) -> &Vec<TempFilterData> {
352         &self.iter.cur_filter_data
353     }
354 
filter_primitives(&self) -> ItemRange<di::FilterPrimitive>355     pub fn filter_primitives(&self) -> ItemRange<di::FilterPrimitive> {
356         self.iter.cur_filter_primitives
357     }
358 }
359 
360 #[derive(PartialEq)]
361 enum Peek {
362     StartPeeking,
363     IsPeeking,
364     NotPeeking,
365 }
366 
367 #[derive(Clone)]
368 pub struct AuxIter<'a, T> {
369     item: T,
370     data: &'a [u8],
371     size: usize,
372 //    _boo: PhantomData<T>,
373 }
374 
375 impl BuiltDisplayList {
from_data(data: Vec<u8>, descriptor: BuiltDisplayListDescriptor) -> Self376     pub fn from_data(data: Vec<u8>, descriptor: BuiltDisplayListDescriptor) -> Self {
377         BuiltDisplayList { data, descriptor }
378     }
379 
into_data(self) -> (Vec<u8>, BuiltDisplayListDescriptor)380     pub fn into_data(self) -> (Vec<u8>, BuiltDisplayListDescriptor) {
381         (self.data, self.descriptor)
382     }
383 
data(&self) -> &[u8]384     pub fn data(&self) -> &[u8] {
385         &self.data[..]
386     }
387 
item_slice(&self) -> &[u8]388     pub fn item_slice(&self) -> &[u8] {
389         &self.data[..self.descriptor.extra_data_offset]
390     }
391 
extra_slice(&self) -> &[u8]392     pub fn extra_slice(&self) -> &[u8] {
393         &self.data[self.descriptor.extra_data_offset..]
394     }
395 
descriptor(&self) -> &BuiltDisplayListDescriptor396     pub fn descriptor(&self) -> &BuiltDisplayListDescriptor {
397         &self.descriptor
398     }
399 
set_send_time_ns(&mut self, time: u64)400     pub fn set_send_time_ns(&mut self, time: u64) {
401         self.descriptor.send_start_time = time;
402     }
403 
times(&self) -> (u64, u64, u64)404     pub fn times(&self) -> (u64, u64, u64) {
405         (
406             self.descriptor.builder_start_time,
407             self.descriptor.builder_finish_time,
408             self.descriptor.send_start_time,
409         )
410     }
411 
gecko_display_list_stats(&self) -> (f64, bool)412     pub fn gecko_display_list_stats(&self) -> (f64, bool) {
413         match self.descriptor.gecko_display_list_type {
414             GeckoDisplayListType::Full(duration) => (duration, true),
415             GeckoDisplayListType::Partial(duration) => (duration, false),
416             _ => (0.0, false)
417         }
418     }
419 
total_clip_nodes(&self) -> usize420     pub fn total_clip_nodes(&self) -> usize {
421         self.descriptor.total_clip_nodes
422     }
423 
total_spatial_nodes(&self) -> usize424     pub fn total_spatial_nodes(&self) -> usize {
425         self.descriptor.total_spatial_nodes
426     }
427 
iter(&self) -> BuiltDisplayListIter428     pub fn iter(&self) -> BuiltDisplayListIter {
429         BuiltDisplayListIter::new(self, self.item_slice(), None)
430     }
431 
extra_data_iter(&self) -> BuiltDisplayListIter432     pub fn extra_data_iter(&self) -> BuiltDisplayListIter {
433         BuiltDisplayListIter::new(self, self.extra_slice(), None)
434     }
435 
iter_with_cache<'a>( &'a self, cache: &'a DisplayItemCache ) -> BuiltDisplayListIter<'a>436     pub fn iter_with_cache<'a>(
437         &'a self,
438         cache: &'a DisplayItemCache
439     ) -> BuiltDisplayListIter<'a> {
440         BuiltDisplayListIter::new(self, self.item_slice(), Some(cache))
441     }
442 
cache_size(&self) -> usize443     pub fn cache_size(&self) -> usize {
444         self.descriptor.cache_size
445     }
446 
447     #[cfg(feature = "serialize")]
serialize_with_iterator<S: Serializer>( serializer: S, mut iterator: BuiltDisplayListIter, ) -> Result<S::Ok, S::Error>448     pub fn serialize_with_iterator<S: Serializer>(
449         serializer: S,
450         mut iterator: BuiltDisplayListIter,
451     ) -> Result<S::Ok, S::Error> {
452         use crate::display_item::DisplayItem as Real;
453         use crate::display_item::DebugDisplayItem as Debug;
454 
455         let mut seq = serializer.serialize_seq(None)?;
456 
457         while let Some(item) = iterator.next_raw() {
458             let serial_di = match *item.item() {
459                 Real::ClipChain(v) => Debug::ClipChain(
460                     v,
461                     item.iter.cur_clip_chain_items.iter().collect()
462                 ),
463                 Real::ScrollFrame(v) => Debug::ScrollFrame(v),
464                 Real::Text(v) => Debug::Text(
465                     v,
466                     item.iter.cur_glyphs.iter().collect()
467                 ),
468                 Real::SetFilterOps => Debug::SetFilterOps(
469                     item.iter.cur_filters.iter().collect()
470                 ),
471                 Real::SetFilterData => {
472                     debug_assert!(!item.iter.cur_filter_data.is_empty(),
473                         "next_raw should have populated cur_filter_data");
474                     let temp_filter_data = &item.iter.cur_filter_data[item.iter.cur_filter_data.len()-1];
475 
476                     let func_types: Vec<di::ComponentTransferFuncType> =
477                         temp_filter_data.func_types.iter().collect();
478                     debug_assert!(func_types.len() == 4,
479                         "someone changed the number of filter funcs without updating this code");
480                     Debug::SetFilterData(di::FilterData {
481                         func_r_type: func_types[0],
482                         r_values: temp_filter_data.r_values.iter().collect(),
483                         func_g_type: func_types[1],
484                         g_values: temp_filter_data.g_values.iter().collect(),
485                         func_b_type: func_types[2],
486                         b_values: temp_filter_data.b_values.iter().collect(),
487                         func_a_type: func_types[3],
488                         a_values: temp_filter_data.a_values.iter().collect(),
489                     })
490                 },
491                 Real::SetFilterPrimitives => Debug::SetFilterPrimitives(
492                     item.iter.cur_filter_primitives.iter().collect()
493                 ),
494                 Real::SetGradientStops => Debug::SetGradientStops(
495                     item.iter.cur_stops.iter().collect()
496                 ),
497                 Real::SetPoints => Debug::SetPoints(
498                     item.iter.cur_points.iter().collect()
499                 ),
500                 Real::RectClip(v) => Debug::RectClip(v),
501                 Real::RoundedRectClip(v) => Debug::RoundedRectClip(v),
502                 Real::ImageMaskClip(v) => Debug::ImageMaskClip(v),
503                 Real::StickyFrame(v) => Debug::StickyFrame(v),
504                 Real::Rectangle(v) => Debug::Rectangle(v),
505                 Real::ClearRectangle(v) => Debug::ClearRectangle(v),
506                 Real::HitTest(v) => Debug::HitTest(v),
507                 Real::Line(v) => Debug::Line(v),
508                 Real::Image(v) => Debug::Image(v),
509                 Real::RepeatingImage(v) => Debug::RepeatingImage(v),
510                 Real::YuvImage(v) => Debug::YuvImage(v),
511                 Real::Border(v) => Debug::Border(v),
512                 Real::BoxShadow(v) => Debug::BoxShadow(v),
513                 Real::Gradient(v) => Debug::Gradient(v),
514                 Real::RadialGradient(v) => Debug::RadialGradient(v),
515                 Real::ConicGradient(v) => Debug::ConicGradient(v),
516                 Real::Iframe(v) => Debug::Iframe(v),
517                 Real::PushReferenceFrame(v) => Debug::PushReferenceFrame(v),
518                 Real::PushStackingContext(v) => Debug::PushStackingContext(v),
519                 Real::PushShadow(v) => Debug::PushShadow(v),
520                 Real::BackdropFilter(v) => Debug::BackdropFilter(v),
521 
522                 Real::PopReferenceFrame => Debug::PopReferenceFrame,
523                 Real::PopStackingContext => Debug::PopStackingContext,
524                 Real::PopAllShadows => Debug::PopAllShadows,
525                 Real::ReuseItems(_) |
526                 Real::RetainedItems(_) => unreachable!("Unexpected item"),
527             };
528             seq.serialize_element(&serial_di)?
529         }
530         seq.end()
531     }
532 }
533 
534 /// Returns the byte-range the slice occupied.
skip_slice<'a, T: peek_poke::Peek>(data: &mut &'a [u8]) -> ItemRange<'a, T>535 fn skip_slice<'a, T: peek_poke::Peek>(data: &mut &'a [u8]) -> ItemRange<'a, T> {
536     let mut skip_offset = 0usize;
537     *data = peek_from_slice(data, &mut skip_offset);
538     let (skip, rest) = data.split_at(skip_offset);
539 
540     // Adjust data pointer to skip read values
541     *data = rest;
542 
543     ItemRange {
544         bytes: skip,
545         _boo: PhantomData,
546     }
547 }
548 
549 impl<'a> BuiltDisplayListIter<'a> {
new( list: &'a BuiltDisplayList, data: &'a [u8], cache: Option<&'a DisplayItemCache>, ) -> Self550     pub fn new(
551         list: &'a BuiltDisplayList,
552         data: &'a [u8],
553         cache: Option<&'a DisplayItemCache>,
554     ) -> Self {
555         Self {
556             list,
557             data,
558             cache,
559             pending_items: [].iter(),
560             cur_cached_item: None,
561             cur_item: di::DisplayItem::PopStackingContext,
562             cur_stops: ItemRange::default(),
563             cur_glyphs: ItemRange::default(),
564             cur_filters: ItemRange::default(),
565             cur_filter_data: Vec::new(),
566             cur_filter_primitives: ItemRange::default(),
567             cur_clip_chain_items: ItemRange::default(),
568             cur_points: ItemRange::default(),
569             peeking: Peek::NotPeeking,
570             debug_stats: DebugStats {
571                 last_addr: data.as_ptr() as usize,
572                 stats: HashMap::default(),
573             },
574         }
575     }
576 
sub_iter(&self) -> Self577     pub fn sub_iter(&self) -> Self {
578         let mut iter = BuiltDisplayListIter::new(
579             self.list, self.data, self.cache
580         );
581         iter.pending_items = self.pending_items.clone();
582         iter
583     }
584 
display_list(&self) -> &'a BuiltDisplayList585     pub fn display_list(&self) -> &'a BuiltDisplayList {
586         self.list
587     }
588 
current_item(&self) -> &di::DisplayItem589     pub fn current_item(&self) -> &di::DisplayItem {
590         match self.cur_cached_item {
591             Some(cached_item) => cached_item.display_item(),
592             None => &self.cur_item
593         }
594     }
595 
cached_item_range_or<T>( &self, data: ItemRange<'a, T> ) -> ItemRange<'a, T>596     fn cached_item_range_or<T>(
597         &self,
598         data: ItemRange<'a, T>
599     ) -> ItemRange<'a, T> {
600         match self.cur_cached_item {
601             Some(cached_item) => cached_item.data_as_item_range(),
602             None => data,
603         }
604     }
605 
glyphs(&self) -> ItemRange<GlyphInstance>606     pub fn glyphs(&self) -> ItemRange<GlyphInstance> {
607         self.cached_item_range_or(self.cur_glyphs)
608     }
609 
gradient_stops(&self) -> ItemRange<di::GradientStop>610     pub fn gradient_stops(&self) -> ItemRange<di::GradientStop> {
611         self.cached_item_range_or(self.cur_stops)
612     }
613 
advance_pending_items(&mut self) -> bool614     fn advance_pending_items(&mut self) -> bool {
615         self.cur_cached_item = self.pending_items.next();
616         self.cur_cached_item.is_some()
617     }
618 
next<'b>(&'b mut self) -> Option<DisplayItemRef<'a, 'b>>619     pub fn next<'b>(&'b mut self) -> Option<DisplayItemRef<'a, 'b>> {
620         use crate::DisplayItem::*;
621 
622         match self.peeking {
623             Peek::IsPeeking => {
624                 self.peeking = Peek::NotPeeking;
625                 return Some(self.as_ref());
626             }
627             Peek::StartPeeking => {
628                 self.peeking = Peek::IsPeeking;
629             }
630             Peek::NotPeeking => { /* do nothing */ }
631         }
632 
633         // Don't let these bleed into another item
634         self.cur_stops = ItemRange::default();
635         self.cur_clip_chain_items = ItemRange::default();
636         self.cur_points = ItemRange::default();
637         self.cur_filters = ItemRange::default();
638         self.cur_filter_primitives = ItemRange::default();
639         self.cur_filter_data.clear();
640 
641         loop {
642             self.next_raw()?;
643             match self.cur_item {
644                 SetGradientStops |
645                 SetFilterOps |
646                 SetFilterData |
647                 SetFilterPrimitives |
648                 SetPoints => {
649                     // These are marker items for populating other display items, don't yield them.
650                     continue;
651                 }
652                 _ => {
653                     break;
654                 }
655             }
656         }
657 
658         Some(self.as_ref())
659     }
660 
661     /// Gets the next display item, even if it's a dummy. Also doesn't handle peeking
662     /// and may leave irrelevant ranges live (so a Clip may have GradientStops if
663     /// for some reason you ask).
next_raw<'b>(&'b mut self) -> Option<DisplayItemRef<'a, 'b>>664     pub fn next_raw<'b>(&'b mut self) -> Option<DisplayItemRef<'a, 'b>> {
665         use crate::DisplayItem::*;
666 
667         if self.advance_pending_items() {
668             return Some(self.as_ref());
669         }
670 
671         // A "red zone" of DisplayItem::max_size() bytes has been added to the
672         // end of the serialized display list. If this amount, or less, is
673         // remaining then we've reached the end of the display list.
674         if self.data.len() <= di::DisplayItem::max_size() {
675             return None;
676         }
677 
678         self.data = peek_from_slice(self.data, &mut self.cur_item);
679         self.log_item_stats();
680 
681         match self.cur_item {
682             SetGradientStops => {
683                 self.cur_stops = skip_slice::<di::GradientStop>(&mut self.data);
684                 self.debug_stats.log_slice("set_gradient_stops.stops", &self.cur_stops);
685             }
686             SetFilterOps => {
687                 self.cur_filters = skip_slice::<di::FilterOp>(&mut self.data);
688                 self.debug_stats.log_slice("set_filter_ops.ops", &self.cur_filters);
689             }
690             SetFilterData => {
691                 self.cur_filter_data.push(TempFilterData {
692                     func_types: skip_slice::<di::ComponentTransferFuncType>(&mut self.data),
693                     r_values: skip_slice::<f32>(&mut self.data),
694                     g_values: skip_slice::<f32>(&mut self.data),
695                     b_values: skip_slice::<f32>(&mut self.data),
696                     a_values: skip_slice::<f32>(&mut self.data),
697                 });
698 
699                 let data = *self.cur_filter_data.last().unwrap();
700                 self.debug_stats.log_slice("set_filter_data.func_types", &data.func_types);
701                 self.debug_stats.log_slice("set_filter_data.r_values", &data.r_values);
702                 self.debug_stats.log_slice("set_filter_data.g_values", &data.g_values);
703                 self.debug_stats.log_slice("set_filter_data.b_values", &data.b_values);
704                 self.debug_stats.log_slice("set_filter_data.a_values", &data.a_values);
705             }
706             SetFilterPrimitives => {
707                 self.cur_filter_primitives = skip_slice::<di::FilterPrimitive>(&mut self.data);
708                 self.debug_stats.log_slice("set_filter_primitives.primitives", &self.cur_filter_primitives);
709             }
710             SetPoints => {
711                 self.cur_points = skip_slice::<LayoutPoint>(&mut self.data);
712                 self.debug_stats.log_slice("set_points.points", &self.cur_points);
713             }
714             ClipChain(_) => {
715                 self.cur_clip_chain_items = skip_slice::<di::ClipId>(&mut self.data);
716                 self.debug_stats.log_slice("clip_chain.clip_ids", &self.cur_clip_chain_items);
717             }
718             Text(_) => {
719                 self.cur_glyphs = skip_slice::<GlyphInstance>(&mut self.data);
720                 self.debug_stats.log_slice("text.glyphs", &self.cur_glyphs);
721             }
722             ReuseItems(key) => {
723                 match self.cache {
724                     Some(cache) => {
725                         self.pending_items = cache.get_items(key).iter();
726                         self.advance_pending_items();
727                     }
728                     None => {
729                         unreachable!("Cache marker without cache!");
730                     }
731                 }
732             }
733             _ => { /* do nothing */ }
734         }
735 
736         Some(self.as_ref())
737     }
738 
as_ref<'b>(&'b self) -> DisplayItemRef<'a, 'b>739     pub fn as_ref<'b>(&'b self) -> DisplayItemRef<'a, 'b> {
740         DisplayItemRef {
741             iter: self,
742         }
743     }
744 
skip_current_stacking_context(&mut self)745     pub fn skip_current_stacking_context(&mut self) {
746         let mut depth = 0;
747         while let Some(item) = self.next() {
748             match *item.item() {
749                 di::DisplayItem::PushStackingContext(..) => depth += 1,
750                 di::DisplayItem::PopStackingContext if depth == 0 => return,
751                 di::DisplayItem::PopStackingContext => depth -= 1,
752                 _ => {}
753             }
754         }
755     }
756 
current_stacking_context_empty(&mut self) -> bool757     pub fn current_stacking_context_empty(&mut self) -> bool {
758         match self.peek() {
759             Some(item) => *item.item() == di::DisplayItem::PopStackingContext,
760             None => true,
761         }
762     }
763 
peek<'b>(&'b mut self) -> Option<DisplayItemRef<'a, 'b>>764     pub fn peek<'b>(&'b mut self) -> Option<DisplayItemRef<'a, 'b>> {
765         if self.peeking == Peek::NotPeeking {
766             self.peeking = Peek::StartPeeking;
767             self.next()
768         } else {
769             Some(self.as_ref())
770         }
771     }
772 
773     /// Get the debug stats for what this iterator has deserialized.
774     /// Should always be empty in release builds.
debug_stats(&mut self) -> Vec<(&'static str, ItemStats)>775     pub fn debug_stats(&mut self) -> Vec<(&'static str, ItemStats)> {
776         let mut result = self.debug_stats.stats.drain().collect::<Vec<_>>();
777         result.sort_by_key(|stats| stats.0);
778         result
779     }
780 
781     /// Adds the debug stats from another to our own, assuming we are a sub-iter of the other
782     /// (so we can ignore where they were in the traversal).
merge_debug_stats_from(&mut self, other: &mut Self)783     pub fn merge_debug_stats_from(&mut self, other: &mut Self) {
784         for (key, other_entry) in other.debug_stats.stats.iter() {
785             let entry = self.debug_stats.stats.entry(key).or_default();
786 
787             entry.total_count += other_entry.total_count;
788             entry.num_bytes += other_entry.num_bytes;
789         }
790     }
791 
792     /// Logs stats for the last deserialized display item
793     #[cfg(feature = "display_list_stats")]
log_item_stats(&mut self)794     fn log_item_stats(&mut self) {
795         self.debug_stats.log_item(self.data, &self.cur_item);
796     }
797 
798     #[cfg(not(feature = "display_list_stats"))]
log_item_stats(&mut self)799     fn log_item_stats(&mut self) { /* no-op */ }
800 }
801 
802 impl<'a, T> AuxIter<'a, T> {
new(item: T, mut data: &'a [u8]) -> Self803     pub fn new(item: T, mut data: &'a [u8]) -> Self {
804         let mut size = 0usize;
805         if !data.is_empty() {
806             data = peek_from_slice(data, &mut size);
807         };
808 
809         AuxIter {
810             item,
811             data,
812             size,
813 //            _boo: PhantomData,
814         }
815     }
816 }
817 
818 impl<'a, T: Copy + peek_poke::Peek> Iterator for AuxIter<'a, T> {
819     type Item = T;
820 
next(&mut self) -> Option<Self::Item>821     fn next(&mut self) -> Option<Self::Item> {
822         if self.size == 0 {
823             None
824         } else {
825             self.size -= 1;
826             self.data = peek_from_slice(self.data, &mut self.item);
827             Some(self.item)
828         }
829     }
830 
size_hint(&self) -> (usize, Option<usize>)831     fn size_hint(&self) -> (usize, Option<usize>) {
832         (self.size, Some(self.size))
833     }
834 }
835 
836 impl<'a, T: Copy + peek_poke::Peek> ::std::iter::ExactSizeIterator for AuxIter<'a, T> {}
837 
838 #[cfg(feature = "serialize")]
839 impl Serialize for BuiltDisplayList {
serialize<S: Serializer>( &self, serializer: S ) -> Result<S::Ok, S::Error>840     fn serialize<S: Serializer>(
841         &self,
842         serializer: S
843     ) -> Result<S::Ok, S::Error> {
844         Self::serialize_with_iterator(serializer, self.iter())
845     }
846 }
847 
848 // The purpose of this implementation is to deserialize
849 // a display list from one format just to immediately
850 // serialize then into a "built" `Vec<u8>`.
851 
852 #[cfg(feature = "deserialize")]
853 impl<'de> Deserialize<'de> for BuiltDisplayList {
deserialize<D: Deserializer<'de>>( deserializer: D ) -> Result<Self, D::Error>854     fn deserialize<D: Deserializer<'de>>(
855         deserializer: D
856     ) -> Result<Self, D::Error> {
857         use crate::display_item::DisplayItem as Real;
858         use crate::display_item::DebugDisplayItem as Debug;
859 
860         let list = Vec::<Debug>::deserialize(deserializer)?;
861 
862         let mut data = Vec::new();
863         let mut temp = Vec::new();
864         let mut total_clip_nodes = FIRST_CLIP_NODE_INDEX;
865         let mut total_spatial_nodes = FIRST_SPATIAL_NODE_INDEX;
866         for complete in list {
867             let item = match complete {
868                 Debug::ClipChain(v, clip_chain_ids) => {
869                     DisplayListBuilder::push_iter_impl(&mut temp, clip_chain_ids);
870                     Real::ClipChain(v)
871                 }
872                 Debug::ScrollFrame(v) => {
873                     total_spatial_nodes += 1;
874                     total_clip_nodes += 1;
875                     Real::ScrollFrame(v)
876                 }
877                 Debug::StickyFrame(v) => {
878                     total_spatial_nodes += 1;
879                     Real::StickyFrame(v)
880                 }
881                 Debug::Text(v, glyphs) => {
882                     DisplayListBuilder::push_iter_impl(&mut temp, glyphs);
883                     Real::Text(v)
884                 },
885                 Debug::Iframe(v) => {
886                     total_clip_nodes += 1;
887                     Real::Iframe(v)
888                 }
889                 Debug::PushReferenceFrame(v) => {
890                     total_spatial_nodes += 1;
891                     Real::PushReferenceFrame(v)
892                 }
893                 Debug::SetFilterOps(filters) => {
894                     DisplayListBuilder::push_iter_impl(&mut temp, filters);
895                     Real::SetFilterOps
896                 },
897                 Debug::SetFilterData(filter_data) => {
898                     let func_types: Vec<di::ComponentTransferFuncType> =
899                         [filter_data.func_r_type,
900                          filter_data.func_g_type,
901                          filter_data.func_b_type,
902                          filter_data.func_a_type].to_vec();
903                     DisplayListBuilder::push_iter_impl(&mut temp, func_types);
904                     DisplayListBuilder::push_iter_impl(&mut temp, filter_data.r_values);
905                     DisplayListBuilder::push_iter_impl(&mut temp, filter_data.g_values);
906                     DisplayListBuilder::push_iter_impl(&mut temp, filter_data.b_values);
907                     DisplayListBuilder::push_iter_impl(&mut temp, filter_data.a_values);
908                     Real::SetFilterData
909                 },
910                 Debug::SetFilterPrimitives(filter_primitives) => {
911                     DisplayListBuilder::push_iter_impl(&mut temp, filter_primitives);
912                     Real::SetFilterPrimitives
913                 }
914                 Debug::SetGradientStops(stops) => {
915                     DisplayListBuilder::push_iter_impl(&mut temp, stops);
916                     Real::SetGradientStops
917                 },
918                 Debug::SetPoints(points) => {
919                     DisplayListBuilder::push_iter_impl(&mut temp, points);
920                     Real::SetPoints
921                 },
922                 Debug::RectClip(v) => Real::RectClip(v),
923                 Debug::RoundedRectClip(v) => Real::RoundedRectClip(v),
924                 Debug::ImageMaskClip(v) => Real::ImageMaskClip(v),
925                 Debug::Rectangle(v) => Real::Rectangle(v),
926                 Debug::ClearRectangle(v) => Real::ClearRectangle(v),
927                 Debug::HitTest(v) => Real::HitTest(v),
928                 Debug::Line(v) => Real::Line(v),
929                 Debug::Image(v) => Real::Image(v),
930                 Debug::RepeatingImage(v) => Real::RepeatingImage(v),
931                 Debug::YuvImage(v) => Real::YuvImage(v),
932                 Debug::Border(v) => Real::Border(v),
933                 Debug::BoxShadow(v) => Real::BoxShadow(v),
934                 Debug::Gradient(v) => Real::Gradient(v),
935                 Debug::RadialGradient(v) => Real::RadialGradient(v),
936                 Debug::ConicGradient(v) => Real::ConicGradient(v),
937                 Debug::PushStackingContext(v) => Real::PushStackingContext(v),
938                 Debug::PushShadow(v) => Real::PushShadow(v),
939                 Debug::BackdropFilter(v) => Real::BackdropFilter(v),
940 
941                 Debug::PopStackingContext => Real::PopStackingContext,
942                 Debug::PopReferenceFrame => Real::PopReferenceFrame,
943                 Debug::PopAllShadows => Real::PopAllShadows,
944             };
945             poke_into_vec(&item, &mut data);
946             // the aux data is serialized after the item, hence the temporary
947             data.extend(temp.drain(..));
948         }
949 
950         // Add `DisplayItem::max_size` zone of zeroes to the end of display list
951         // so there is at least this amount available in the display list during
952         // serialization.
953         ensure_red_zone::<di::DisplayItem>(&mut data);
954         let extra_data_offset = data.len();
955 
956         Ok(BuiltDisplayList {
957             data,
958             descriptor: BuiltDisplayListDescriptor {
959                 gecko_display_list_type: GeckoDisplayListType::None,
960                 builder_start_time: 0,
961                 builder_finish_time: 1,
962                 send_start_time: 1,
963                 total_clip_nodes,
964                 total_spatial_nodes,
965                 extra_data_offset,
966                 cache_size: 0,
967             },
968         })
969     }
970 }
971 
972 #[derive(Clone, Debug)]
973 pub struct SaveState {
974     dl_len: usize,
975     next_clip_index: usize,
976     next_spatial_index: usize,
977     next_clip_chain_id: u64,
978 }
979 
980 /// DisplayListSection determines the target buffer for the display items.
981 pub enum DisplayListSection {
982     /// The main/default buffer: contains item data and item group markers.
983     Data,
984     /// Auxiliary buffer: contains the item data for item groups.
985     ExtraData,
986     /// Temporary buffer: contains the data for pending item group. Flushed to
987     /// one of the buffers above, after item grouping finishes.
988     Chunk,
989 }
990 
991 #[derive(Clone)]
992 pub struct DisplayListBuilder {
993     pub data: Vec<u8>,
994     pub pipeline_id: PipelineId,
995 
996     extra_data: Vec<u8>,
997     pending_chunk: Vec<u8>,
998     writing_to_chunk: bool,
999 
1000     next_clip_index: usize,
1001     next_spatial_index: usize,
1002     next_clip_chain_id: u64,
1003     builder_start_time: u64,
1004 
1005     save_state: Option<SaveState>,
1006 
1007     cache_size: usize,
1008     serialized_content_buffer: Option<String>,
1009 }
1010 
1011 impl DisplayListBuilder {
new(pipeline_id: PipelineId) -> Self1012     pub fn new(pipeline_id: PipelineId) -> Self {
1013         Self::with_capacity(pipeline_id, 0)
1014     }
1015 
with_capacity( pipeline_id: PipelineId, capacity: usize, ) -> Self1016     pub fn with_capacity(
1017         pipeline_id: PipelineId,
1018         capacity: usize,
1019     ) -> Self {
1020         let start_time = precise_time_ns();
1021 
1022         DisplayListBuilder {
1023             data: Vec::with_capacity(capacity),
1024             pipeline_id,
1025 
1026             extra_data: Vec::new(),
1027             pending_chunk: Vec::new(),
1028             writing_to_chunk: false,
1029 
1030             next_clip_index: FIRST_CLIP_NODE_INDEX,
1031             next_spatial_index: FIRST_SPATIAL_NODE_INDEX,
1032             next_clip_chain_id: 0,
1033             builder_start_time: start_time,
1034             save_state: None,
1035             cache_size: 0,
1036             serialized_content_buffer: None,
1037         }
1038     }
1039 
1040     /// Saves the current display list state, so it may be `restore()`'d.
1041     ///
1042     /// # Conditions:
1043     ///
1044     /// * Doesn't support popping clips that were pushed before the save.
1045     /// * Doesn't support nested saves.
1046     /// * Must call `clear_save()` if the restore becomes unnecessary.
save(&mut self)1047     pub fn save(&mut self) {
1048         assert!(self.save_state.is_none(), "DisplayListBuilder doesn't support nested saves");
1049 
1050         self.save_state = Some(SaveState {
1051             dl_len: self.data.len(),
1052             next_clip_index: self.next_clip_index,
1053             next_spatial_index: self.next_spatial_index,
1054             next_clip_chain_id: self.next_clip_chain_id,
1055         });
1056     }
1057 
1058     /// Restores the state of the builder to when `save()` was last called.
restore(&mut self)1059     pub fn restore(&mut self) {
1060         let state = self.save_state.take().expect("No save to restore DisplayListBuilder from");
1061 
1062         self.data.truncate(state.dl_len);
1063         self.next_clip_index = state.next_clip_index;
1064         self.next_spatial_index = state.next_spatial_index;
1065         self.next_clip_chain_id = state.next_clip_chain_id;
1066     }
1067 
1068     /// Discards the builder's save (indicating the attempted operation was successful).
clear_save(&mut self)1069     pub fn clear_save(&mut self) {
1070         self.save_state.take().expect("No save to clear in DisplayListBuilder");
1071     }
1072 
1073     /// Emits a debug representation of display items in the list, for debugging
1074     /// purposes. If the range's start parameter is specified, only display
1075     /// items starting at that index (inclusive) will be printed. If the range's
1076     /// end parameter is specified, only display items before that index
1077     /// (exclusive) will be printed. Calling this function with end <= start is
1078     /// allowed but is just a waste of CPU cycles. The function emits the
1079     /// debug representation of the selected display items, one per line, with
1080     /// the given indent, to the provided sink object. The return value is
1081     /// the total number of items in the display list, which allows the
1082     /// caller to subsequently invoke this function to only dump the newly-added
1083     /// items.
emit_display_list<W>( &mut self, indent: usize, range: Range<Option<usize>>, mut sink: W, ) -> usize where W: Write1084     pub fn emit_display_list<W>(
1085         &mut self,
1086         indent: usize,
1087         range: Range<Option<usize>>,
1088         mut sink: W,
1089     ) -> usize
1090     where
1091         W: Write
1092     {
1093         let mut temp = BuiltDisplayList::default();
1094         ensure_red_zone::<di::DisplayItem>(&mut self.data);
1095         temp.descriptor.extra_data_offset = self.data.len();
1096         mem::swap(&mut temp.data, &mut self.data);
1097 
1098         let mut index: usize = 0;
1099         {
1100             let mut cache = DisplayItemCache::new();
1101             cache.update(&temp);
1102             let mut iter = temp.iter_with_cache(&cache);
1103             while let Some(item) = iter.next_raw() {
1104                 if index >= range.start.unwrap_or(0) && range.end.map_or(true, |e| index < e) {
1105                     writeln!(sink, "{}{:?}", "  ".repeat(indent), item.item()).unwrap();
1106                 }
1107                 index += 1;
1108             }
1109         }
1110 
1111         self.data = temp.data;
1112         strip_red_zone::<di::DisplayItem>(&mut self.data);
1113         index
1114     }
1115 
1116     /// Print the display items in the list to stdout.
dump_serialized_display_list(&mut self)1117     pub fn dump_serialized_display_list(&mut self) {
1118         self.serialized_content_buffer = Some(String::new());
1119     }
1120 
add_to_display_list_dump<T: std::fmt::Debug>(&mut self, item: T)1121     fn add_to_display_list_dump<T: std::fmt::Debug>(&mut self, item: T) {
1122         if let Some(ref mut content) = self.serialized_content_buffer {
1123             use std::fmt::Write;
1124             write!(content, "{:?}\n", item).expect("DL dump write failed.");
1125         }
1126     }
1127 
1128     /// Returns the default section that DisplayListBuilder will write to,
1129     /// if no section is specified explicitly.
default_section(&self) -> DisplayListSection1130     fn default_section(&self) -> DisplayListSection {
1131         if self.writing_to_chunk {
1132             DisplayListSection::Chunk
1133         } else {
1134             DisplayListSection::Data
1135         }
1136     }
1137 
buffer_from_section( &mut self, section: DisplayListSection ) -> &mut Vec<u8>1138     fn buffer_from_section(
1139         &mut self,
1140         section: DisplayListSection
1141     ) -> &mut Vec<u8> {
1142         match section {
1143             DisplayListSection::Data => &mut self.data,
1144             DisplayListSection::ExtraData => &mut self.extra_data,
1145             DisplayListSection::Chunk => &mut self.pending_chunk,
1146         }
1147     }
1148 
1149     #[inline]
push_item_to_section( &mut self, item: &di::DisplayItem, section: DisplayListSection, )1150     pub fn push_item_to_section(
1151         &mut self,
1152         item: &di::DisplayItem,
1153         section: DisplayListSection,
1154     ) {
1155         poke_into_vec(item, self.buffer_from_section(section));
1156         self.add_to_display_list_dump(item);
1157     }
1158 
1159     /// Add an item to the display list.
1160     ///
1161     /// NOTE: It is usually preferable to use the specialized methods to push
1162     /// display items. Pushing unexpected or invalid items here may
1163     /// result in WebRender panicking or behaving in unexpected ways.
1164     #[inline]
push_item(&mut self, item: &di::DisplayItem)1165     pub fn push_item(&mut self, item: &di::DisplayItem) {
1166         self.push_item_to_section(item, self.default_section());
1167     }
1168 
push_iter_impl<I>(data: &mut Vec<u8>, iter_source: I) where I: IntoIterator, I::IntoIter: ExactSizeIterator, I::Item: Poke,1169     fn push_iter_impl<I>(data: &mut Vec<u8>, iter_source: I)
1170     where
1171         I: IntoIterator,
1172         I::IntoIter: ExactSizeIterator,
1173         I::Item: Poke,
1174     {
1175         let iter = iter_source.into_iter();
1176         let len = iter.len();
1177         // Format:
1178         // payload_byte_size: usize, item_count: usize, [I; item_count]
1179 
1180         // Track the the location of where to write byte size with offsets
1181         // instead of pointers because data may be moved in memory during
1182         // `serialize_iter_fast`.
1183         let byte_size_offset = data.len();
1184 
1185         // We write a dummy value so there's room for later
1186         poke_into_vec(&0usize, data);
1187         poke_into_vec(&len, data);
1188         let count = poke_extend_vec(iter, data);
1189         debug_assert_eq!(len, count, "iterator.len() returned two different values");
1190 
1191         // Add red zone
1192         ensure_red_zone::<I::Item>(data);
1193 
1194         // Now write the actual byte_size
1195         let final_offset = data.len();
1196         debug_assert!(final_offset >= (byte_size_offset + mem::size_of::<usize>()),
1197             "space was never allocated for this array's byte_size");
1198         let byte_size = final_offset - byte_size_offset - mem::size_of::<usize>();
1199         poke_inplace_slice(&byte_size, &mut data[byte_size_offset..]);
1200     }
1201 
1202     /// Push items from an iterator to the display list.
1203     ///
1204     /// NOTE: Pushing unexpected or invalid items to the display list
1205     /// may result in panic and confusion.
push_iter<I>(&mut self, iter: I) where I: IntoIterator, I::IntoIter: ExactSizeIterator, I::Item: Poke,1206     pub fn push_iter<I>(&mut self, iter: I)
1207     where
1208         I: IntoIterator,
1209         I::IntoIter: ExactSizeIterator,
1210         I::Item: Poke,
1211     {
1212         let mut buffer = self.buffer_from_section(self.default_section());
1213         Self::push_iter_impl(&mut buffer, iter);
1214     }
1215 
push_rect( &mut self, common: &di::CommonItemProperties, bounds: LayoutRect, color: ColorF, )1216     pub fn push_rect(
1217         &mut self,
1218         common: &di::CommonItemProperties,
1219         bounds: LayoutRect,
1220         color: ColorF,
1221     ) {
1222         let item = di::DisplayItem::Rectangle(di::RectangleDisplayItem {
1223             common: *common,
1224             color: PropertyBinding::Value(color),
1225             bounds,
1226         });
1227         self.push_item(&item);
1228     }
1229 
push_rect_with_animation( &mut self, common: &di::CommonItemProperties, bounds: LayoutRect, color: PropertyBinding<ColorF>, )1230     pub fn push_rect_with_animation(
1231         &mut self,
1232         common: &di::CommonItemProperties,
1233         bounds: LayoutRect,
1234         color: PropertyBinding<ColorF>,
1235     ) {
1236         let item = di::DisplayItem::Rectangle(di::RectangleDisplayItem {
1237             common: *common,
1238             color,
1239             bounds,
1240         });
1241         self.push_item(&item);
1242     }
1243 
push_clear_rect( &mut self, common: &di::CommonItemProperties, bounds: LayoutRect, )1244     pub fn push_clear_rect(
1245         &mut self,
1246         common: &di::CommonItemProperties,
1247         bounds: LayoutRect,
1248     ) {
1249         let item = di::DisplayItem::ClearRectangle(di::ClearRectangleDisplayItem {
1250             common: *common,
1251             bounds,
1252         });
1253         self.push_item(&item);
1254     }
1255 
push_hit_test( &mut self, common: &di::CommonItemProperties, tag: di::ItemTag, )1256     pub fn push_hit_test(
1257         &mut self,
1258         common: &di::CommonItemProperties,
1259         tag: di::ItemTag,
1260     ) {
1261         let item = di::DisplayItem::HitTest(di::HitTestDisplayItem {
1262             common: *common,
1263             tag,
1264         });
1265         self.push_item(&item);
1266     }
1267 
push_line( &mut self, common: &di::CommonItemProperties, area: &LayoutRect, wavy_line_thickness: f32, orientation: di::LineOrientation, color: &ColorF, style: di::LineStyle, )1268     pub fn push_line(
1269         &mut self,
1270         common: &di::CommonItemProperties,
1271         area: &LayoutRect,
1272         wavy_line_thickness: f32,
1273         orientation: di::LineOrientation,
1274         color: &ColorF,
1275         style: di::LineStyle,
1276     ) {
1277         let item = di::DisplayItem::Line(di::LineDisplayItem {
1278             common: *common,
1279             area: *area,
1280             wavy_line_thickness,
1281             orientation,
1282             color: *color,
1283             style,
1284         });
1285 
1286         self.push_item(&item);
1287     }
1288 
push_image( &mut self, common: &di::CommonItemProperties, bounds: LayoutRect, image_rendering: di::ImageRendering, alpha_type: di::AlphaType, key: ImageKey, color: ColorF, )1289     pub fn push_image(
1290         &mut self,
1291         common: &di::CommonItemProperties,
1292         bounds: LayoutRect,
1293         image_rendering: di::ImageRendering,
1294         alpha_type: di::AlphaType,
1295         key: ImageKey,
1296         color: ColorF,
1297     ) {
1298         let item = di::DisplayItem::Image(di::ImageDisplayItem {
1299             common: *common,
1300             bounds,
1301             image_key: key,
1302             image_rendering,
1303             alpha_type,
1304             color,
1305         });
1306 
1307         self.push_item(&item);
1308     }
1309 
push_repeating_image( &mut self, common: &di::CommonItemProperties, bounds: LayoutRect, stretch_size: LayoutSize, tile_spacing: LayoutSize, image_rendering: di::ImageRendering, alpha_type: di::AlphaType, key: ImageKey, color: ColorF, )1310     pub fn push_repeating_image(
1311         &mut self,
1312         common: &di::CommonItemProperties,
1313         bounds: LayoutRect,
1314         stretch_size: LayoutSize,
1315         tile_spacing: LayoutSize,
1316         image_rendering: di::ImageRendering,
1317         alpha_type: di::AlphaType,
1318         key: ImageKey,
1319         color: ColorF,
1320     ) {
1321         let item = di::DisplayItem::RepeatingImage(di::RepeatingImageDisplayItem {
1322             common: *common,
1323             bounds,
1324             image_key: key,
1325             stretch_size,
1326             tile_spacing,
1327             image_rendering,
1328             alpha_type,
1329             color,
1330         });
1331 
1332         self.push_item(&item);
1333     }
1334 
1335     /// Push a yuv image. All planar data in yuv image should use the same buffer type.
push_yuv_image( &mut self, common: &di::CommonItemProperties, bounds: LayoutRect, yuv_data: di::YuvData, color_depth: ColorDepth, color_space: di::YuvColorSpace, color_range: di::ColorRange, image_rendering: di::ImageRendering, )1336     pub fn push_yuv_image(
1337         &mut self,
1338         common: &di::CommonItemProperties,
1339         bounds: LayoutRect,
1340         yuv_data: di::YuvData,
1341         color_depth: ColorDepth,
1342         color_space: di::YuvColorSpace,
1343         color_range: di::ColorRange,
1344         image_rendering: di::ImageRendering,
1345     ) {
1346         let item = di::DisplayItem::YuvImage(di::YuvImageDisplayItem {
1347             common: *common,
1348             bounds,
1349             yuv_data,
1350             color_depth,
1351             color_space,
1352             color_range,
1353             image_rendering,
1354         });
1355         self.push_item(&item);
1356     }
1357 
push_text( &mut self, common: &di::CommonItemProperties, bounds: LayoutRect, glyphs: &[GlyphInstance], font_key: FontInstanceKey, color: ColorF, glyph_options: Option<GlyphOptions>, )1358     pub fn push_text(
1359         &mut self,
1360         common: &di::CommonItemProperties,
1361         bounds: LayoutRect,
1362         glyphs: &[GlyphInstance],
1363         font_key: FontInstanceKey,
1364         color: ColorF,
1365         glyph_options: Option<GlyphOptions>,
1366     ) {
1367         let item = di::DisplayItem::Text(di::TextDisplayItem {
1368             common: *common,
1369             bounds,
1370             color,
1371             font_key,
1372             glyph_options,
1373         });
1374 
1375         for split_glyphs in glyphs.chunks(MAX_TEXT_RUN_LENGTH) {
1376             self.push_item(&item);
1377             self.push_iter(split_glyphs);
1378         }
1379     }
1380 
1381     /// NOTE: gradients must be pushed in the order they're created
1382     /// because create_gradient stores the stops in anticipation.
create_gradient( &mut self, start_point: LayoutPoint, end_point: LayoutPoint, stops: Vec<di::GradientStop>, extend_mode: di::ExtendMode, ) -> di::Gradient1383     pub fn create_gradient(
1384         &mut self,
1385         start_point: LayoutPoint,
1386         end_point: LayoutPoint,
1387         stops: Vec<di::GradientStop>,
1388         extend_mode: di::ExtendMode,
1389     ) -> di::Gradient {
1390         let mut builder = GradientBuilder::with_stops(stops);
1391         let gradient = builder.gradient(start_point, end_point, extend_mode);
1392         self.push_stops(builder.stops());
1393         gradient
1394     }
1395 
1396     /// NOTE: gradients must be pushed in the order they're created
1397     /// because create_gradient stores the stops in anticipation.
create_radial_gradient( &mut self, center: LayoutPoint, radius: LayoutSize, stops: Vec<di::GradientStop>, extend_mode: di::ExtendMode, ) -> di::RadialGradient1398     pub fn create_radial_gradient(
1399         &mut self,
1400         center: LayoutPoint,
1401         radius: LayoutSize,
1402         stops: Vec<di::GradientStop>,
1403         extend_mode: di::ExtendMode,
1404     ) -> di::RadialGradient {
1405         let mut builder = GradientBuilder::with_stops(stops);
1406         let gradient = builder.radial_gradient(center, radius, extend_mode);
1407         self.push_stops(builder.stops());
1408         gradient
1409     }
1410 
1411     /// NOTE: gradients must be pushed in the order they're created
1412     /// because create_gradient stores the stops in anticipation.
create_conic_gradient( &mut self, center: LayoutPoint, angle: f32, stops: Vec<di::GradientStop>, extend_mode: di::ExtendMode, ) -> di::ConicGradient1413     pub fn create_conic_gradient(
1414         &mut self,
1415         center: LayoutPoint,
1416         angle: f32,
1417         stops: Vec<di::GradientStop>,
1418         extend_mode: di::ExtendMode,
1419     ) -> di::ConicGradient {
1420         let mut builder = GradientBuilder::with_stops(stops);
1421         let gradient = builder.conic_gradient(center, angle, extend_mode);
1422         self.push_stops(builder.stops());
1423         gradient
1424     }
1425 
push_border( &mut self, common: &di::CommonItemProperties, bounds: LayoutRect, widths: LayoutSideOffsets, details: di::BorderDetails, )1426     pub fn push_border(
1427         &mut self,
1428         common: &di::CommonItemProperties,
1429         bounds: LayoutRect,
1430         widths: LayoutSideOffsets,
1431         details: di::BorderDetails,
1432     ) {
1433         let item = di::DisplayItem::Border(di::BorderDisplayItem {
1434             common: *common,
1435             bounds,
1436             details,
1437             widths,
1438         });
1439 
1440         self.push_item(&item);
1441     }
1442 
push_box_shadow( &mut self, common: &di::CommonItemProperties, box_bounds: LayoutRect, offset: LayoutVector2D, color: ColorF, blur_radius: f32, spread_radius: f32, border_radius: di::BorderRadius, clip_mode: di::BoxShadowClipMode, )1443     pub fn push_box_shadow(
1444         &mut self,
1445         common: &di::CommonItemProperties,
1446         box_bounds: LayoutRect,
1447         offset: LayoutVector2D,
1448         color: ColorF,
1449         blur_radius: f32,
1450         spread_radius: f32,
1451         border_radius: di::BorderRadius,
1452         clip_mode: di::BoxShadowClipMode,
1453     ) {
1454         let item = di::DisplayItem::BoxShadow(di::BoxShadowDisplayItem {
1455             common: *common,
1456             box_bounds,
1457             offset,
1458             color,
1459             blur_radius,
1460             spread_radius,
1461             border_radius,
1462             clip_mode,
1463         });
1464 
1465         self.push_item(&item);
1466     }
1467 
1468     /// Pushes a linear gradient to be displayed.
1469     ///
1470     /// The gradient itself is described in the
1471     /// `gradient` parameter. It is drawn on
1472     /// a "tile" with the dimensions from `tile_size`.
1473     /// These tiles are now repeated to the right and
1474     /// to the bottom infinitely. If `tile_spacing`
1475     /// is not zero spacers with the given dimensions
1476     /// are inserted between the tiles as seams.
1477     ///
1478     /// The origin of the tiles is given in `layout.rect.origin`.
1479     /// If the gradient should only be displayed once limit
1480     /// the `layout.rect.size` to a single tile.
1481     /// The gradient is only visible within the local clip.
push_gradient( &mut self, common: &di::CommonItemProperties, bounds: LayoutRect, gradient: di::Gradient, tile_size: LayoutSize, tile_spacing: LayoutSize, )1482     pub fn push_gradient(
1483         &mut self,
1484         common: &di::CommonItemProperties,
1485         bounds: LayoutRect,
1486         gradient: di::Gradient,
1487         tile_size: LayoutSize,
1488         tile_spacing: LayoutSize,
1489     ) {
1490         let item = di::DisplayItem::Gradient(di::GradientDisplayItem {
1491             common: *common,
1492             bounds,
1493             gradient,
1494             tile_size,
1495             tile_spacing,
1496         });
1497 
1498         self.push_item(&item);
1499     }
1500 
1501     /// Pushes a radial gradient to be displayed.
1502     ///
1503     /// See [`push_gradient`](#method.push_gradient) for explanation.
push_radial_gradient( &mut self, common: &di::CommonItemProperties, bounds: LayoutRect, gradient: di::RadialGradient, tile_size: LayoutSize, tile_spacing: LayoutSize, )1504     pub fn push_radial_gradient(
1505         &mut self,
1506         common: &di::CommonItemProperties,
1507         bounds: LayoutRect,
1508         gradient: di::RadialGradient,
1509         tile_size: LayoutSize,
1510         tile_spacing: LayoutSize,
1511     ) {
1512         let item = di::DisplayItem::RadialGradient(di::RadialGradientDisplayItem {
1513             common: *common,
1514             bounds,
1515             gradient,
1516             tile_size,
1517             tile_spacing,
1518         });
1519 
1520         self.push_item(&item);
1521     }
1522 
1523     /// Pushes a conic gradient to be displayed.
1524     ///
1525     /// See [`push_gradient`](#method.push_gradient) for explanation.
push_conic_gradient( &mut self, common: &di::CommonItemProperties, bounds: LayoutRect, gradient: di::ConicGradient, tile_size: LayoutSize, tile_spacing: LayoutSize, )1526     pub fn push_conic_gradient(
1527         &mut self,
1528         common: &di::CommonItemProperties,
1529         bounds: LayoutRect,
1530         gradient: di::ConicGradient,
1531         tile_size: LayoutSize,
1532         tile_spacing: LayoutSize,
1533     ) {
1534         let item = di::DisplayItem::ConicGradient(di::ConicGradientDisplayItem {
1535             common: *common,
1536             bounds,
1537             gradient,
1538             tile_size,
1539             tile_spacing,
1540         });
1541 
1542         self.push_item(&item);
1543     }
1544 
push_reference_frame( &mut self, origin: LayoutPoint, parent_spatial_id: di::SpatialId, transform_style: di::TransformStyle, transform: PropertyBinding<LayoutTransform>, kind: di::ReferenceFrameKind, ) -> di::SpatialId1545     pub fn push_reference_frame(
1546         &mut self,
1547         origin: LayoutPoint,
1548         parent_spatial_id: di::SpatialId,
1549         transform_style: di::TransformStyle,
1550         transform: PropertyBinding<LayoutTransform>,
1551         kind: di::ReferenceFrameKind,
1552     ) -> di::SpatialId {
1553         let id = self.generate_spatial_index();
1554 
1555         let item = di::DisplayItem::PushReferenceFrame(di::ReferenceFrameDisplayListItem {
1556             parent_spatial_id,
1557             origin,
1558             reference_frame: di::ReferenceFrame {
1559                 transform_style,
1560                 transform: di::ReferenceTransformBinding::Static {
1561                     binding: transform,
1562                 },
1563                 kind,
1564                 id,
1565             },
1566         });
1567 
1568         self.push_item(&item);
1569         id
1570     }
1571 
push_computed_frame( &mut self, origin: LayoutPoint, parent_spatial_id: di::SpatialId, scale_from: Option<LayoutSize>, vertical_flip: bool, rotation: di::Rotation, ) -> di::SpatialId1572     pub fn push_computed_frame(
1573         &mut self,
1574         origin: LayoutPoint,
1575         parent_spatial_id: di::SpatialId,
1576         scale_from: Option<LayoutSize>,
1577         vertical_flip: bool,
1578         rotation: di::Rotation,
1579     ) -> di::SpatialId {
1580         let id = self.generate_spatial_index();
1581 
1582         let item = di::DisplayItem::PushReferenceFrame(di::ReferenceFrameDisplayListItem {
1583             parent_spatial_id,
1584             origin,
1585             reference_frame: di::ReferenceFrame {
1586                 transform_style: di::TransformStyle::Flat,
1587                 transform: di::ReferenceTransformBinding::Computed {
1588                     scale_from,
1589                     vertical_flip,
1590                     rotation,
1591                 },
1592                 kind: di::ReferenceFrameKind::Transform {
1593                     is_2d_scale_translation: false,
1594                     should_snap: false,
1595                 },
1596                 id,
1597             },
1598         });
1599 
1600         self.push_item(&item);
1601         id
1602     }
1603 
pop_reference_frame(&mut self)1604     pub fn pop_reference_frame(&mut self) {
1605         self.push_item(&di::DisplayItem::PopReferenceFrame);
1606     }
1607 
push_stacking_context( &mut self, origin: LayoutPoint, spatial_id: di::SpatialId, prim_flags: di::PrimitiveFlags, clip_id: Option<di::ClipId>, transform_style: di::TransformStyle, mix_blend_mode: di::MixBlendMode, filters: &[di::FilterOp], filter_datas: &[di::FilterData], filter_primitives: &[di::FilterPrimitive], raster_space: di::RasterSpace, flags: di::StackingContextFlags, )1608     pub fn push_stacking_context(
1609         &mut self,
1610         origin: LayoutPoint,
1611         spatial_id: di::SpatialId,
1612         prim_flags: di::PrimitiveFlags,
1613         clip_id: Option<di::ClipId>,
1614         transform_style: di::TransformStyle,
1615         mix_blend_mode: di::MixBlendMode,
1616         filters: &[di::FilterOp],
1617         filter_datas: &[di::FilterData],
1618         filter_primitives: &[di::FilterPrimitive],
1619         raster_space: di::RasterSpace,
1620         flags: di::StackingContextFlags,
1621     ) {
1622         self.push_filters(filters, filter_datas, filter_primitives);
1623 
1624         let item = di::DisplayItem::PushStackingContext(di::PushStackingContextDisplayItem {
1625             origin,
1626             spatial_id,
1627             prim_flags,
1628             stacking_context: di::StackingContext {
1629                 transform_style,
1630                 mix_blend_mode,
1631                 clip_id,
1632                 raster_space,
1633                 flags,
1634             },
1635         });
1636 
1637         self.push_item(&item);
1638     }
1639 
1640     /// Helper for examples/ code.
push_simple_stacking_context( &mut self, origin: LayoutPoint, spatial_id: di::SpatialId, prim_flags: di::PrimitiveFlags, )1641     pub fn push_simple_stacking_context(
1642         &mut self,
1643         origin: LayoutPoint,
1644         spatial_id: di::SpatialId,
1645         prim_flags: di::PrimitiveFlags,
1646     ) {
1647         self.push_simple_stacking_context_with_filters(
1648             origin,
1649             spatial_id,
1650             prim_flags,
1651             &[],
1652             &[],
1653             &[],
1654         );
1655     }
1656 
1657     /// Helper for examples/ code.
push_simple_stacking_context_with_filters( &mut self, origin: LayoutPoint, spatial_id: di::SpatialId, prim_flags: di::PrimitiveFlags, filters: &[di::FilterOp], filter_datas: &[di::FilterData], filter_primitives: &[di::FilterPrimitive], )1658     pub fn push_simple_stacking_context_with_filters(
1659         &mut self,
1660         origin: LayoutPoint,
1661         spatial_id: di::SpatialId,
1662         prim_flags: di::PrimitiveFlags,
1663         filters: &[di::FilterOp],
1664         filter_datas: &[di::FilterData],
1665         filter_primitives: &[di::FilterPrimitive],
1666     ) {
1667         self.push_stacking_context(
1668             origin,
1669             spatial_id,
1670             prim_flags,
1671             None,
1672             di::TransformStyle::Flat,
1673             di::MixBlendMode::Normal,
1674             filters,
1675             filter_datas,
1676             filter_primitives,
1677             di::RasterSpace::Screen,
1678             di::StackingContextFlags::empty(),
1679         );
1680     }
1681 
pop_stacking_context(&mut self)1682     pub fn pop_stacking_context(&mut self) {
1683         self.push_item(&di::DisplayItem::PopStackingContext);
1684     }
1685 
push_stops(&mut self, stops: &[di::GradientStop])1686     pub fn push_stops(&mut self, stops: &[di::GradientStop]) {
1687         if stops.is_empty() {
1688             return;
1689         }
1690         self.push_item(&di::DisplayItem::SetGradientStops);
1691         self.push_iter(stops);
1692     }
1693 
push_backdrop_filter( &mut self, common: &di::CommonItemProperties, filters: &[di::FilterOp], filter_datas: &[di::FilterData], filter_primitives: &[di::FilterPrimitive], )1694     pub fn push_backdrop_filter(
1695         &mut self,
1696         common: &di::CommonItemProperties,
1697         filters: &[di::FilterOp],
1698         filter_datas: &[di::FilterData],
1699         filter_primitives: &[di::FilterPrimitive],
1700     ) {
1701         self.push_filters(filters, filter_datas, filter_primitives);
1702 
1703         let item = di::DisplayItem::BackdropFilter(di::BackdropFilterDisplayItem {
1704             common: *common,
1705         });
1706         self.push_item(&item);
1707     }
1708 
push_filters( &mut self, filters: &[di::FilterOp], filter_datas: &[di::FilterData], filter_primitives: &[di::FilterPrimitive], )1709     pub fn push_filters(
1710         &mut self,
1711         filters: &[di::FilterOp],
1712         filter_datas: &[di::FilterData],
1713         filter_primitives: &[di::FilterPrimitive],
1714     ) {
1715         if !filters.is_empty() {
1716             self.push_item(&di::DisplayItem::SetFilterOps);
1717             self.push_iter(filters);
1718         }
1719 
1720         for filter_data in filter_datas {
1721             let func_types = [
1722                 filter_data.func_r_type, filter_data.func_g_type,
1723                 filter_data.func_b_type, filter_data.func_a_type];
1724             self.push_item(&di::DisplayItem::SetFilterData);
1725             self.push_iter(&func_types);
1726             self.push_iter(&filter_data.r_values);
1727             self.push_iter(&filter_data.g_values);
1728             self.push_iter(&filter_data.b_values);
1729             self.push_iter(&filter_data.a_values);
1730         }
1731 
1732         if !filter_primitives.is_empty() {
1733             self.push_item(&di::DisplayItem::SetFilterPrimitives);
1734             self.push_iter(filter_primitives);
1735         }
1736     }
1737 
generate_clip_index(&mut self) -> di::ClipId1738     fn generate_clip_index(&mut self) -> di::ClipId {
1739         self.next_clip_index += 1;
1740         di::ClipId::Clip(self.next_clip_index - 1, self.pipeline_id)
1741     }
1742 
generate_spatial_index(&mut self) -> di::SpatialId1743     fn generate_spatial_index(&mut self) -> di::SpatialId {
1744         self.next_spatial_index += 1;
1745         di::SpatialId::new(self.next_spatial_index - 1, self.pipeline_id)
1746     }
1747 
generate_clip_chain_id(&mut self) -> di::ClipChainId1748     fn generate_clip_chain_id(&mut self) -> di::ClipChainId {
1749         self.next_clip_chain_id += 1;
1750         di::ClipChainId(self.next_clip_chain_id - 1, self.pipeline_id)
1751     }
1752 
define_scroll_frame( &mut self, parent_space_and_clip: &di::SpaceAndClipInfo, external_id: di::ExternalScrollId, content_rect: LayoutRect, clip_rect: LayoutRect, scroll_sensitivity: di::ScrollSensitivity, external_scroll_offset: LayoutVector2D, ) -> di::SpaceAndClipInfo1753     pub fn define_scroll_frame(
1754         &mut self,
1755         parent_space_and_clip: &di::SpaceAndClipInfo,
1756         external_id: di::ExternalScrollId,
1757         content_rect: LayoutRect,
1758         clip_rect: LayoutRect,
1759         scroll_sensitivity: di::ScrollSensitivity,
1760         external_scroll_offset: LayoutVector2D,
1761     ) -> di::SpaceAndClipInfo {
1762         let clip_id = self.generate_clip_index();
1763         let scroll_frame_id = self.generate_spatial_index();
1764         let item = di::DisplayItem::ScrollFrame(di::ScrollFrameDisplayItem {
1765             content_rect,
1766             clip_rect,
1767             parent_space_and_clip: *parent_space_and_clip,
1768             clip_id,
1769             scroll_frame_id,
1770             external_id,
1771             scroll_sensitivity,
1772             external_scroll_offset,
1773         });
1774 
1775         self.push_item(&item);
1776 
1777         di::SpaceAndClipInfo {
1778             spatial_id: scroll_frame_id,
1779             clip_id,
1780         }
1781     }
1782 
define_clip_chain<I>( &mut self, parent: Option<di::ClipChainId>, clips: I, ) -> di::ClipChainId where I: IntoIterator<Item = di::ClipId>, I::IntoIter: ExactSizeIterator + Clone,1783     pub fn define_clip_chain<I>(
1784         &mut self,
1785         parent: Option<di::ClipChainId>,
1786         clips: I,
1787     ) -> di::ClipChainId
1788     where
1789         I: IntoIterator<Item = di::ClipId>,
1790         I::IntoIter: ExactSizeIterator + Clone,
1791     {
1792         let id = self.generate_clip_chain_id();
1793         self.push_item(&di::DisplayItem::ClipChain(di::ClipChainItem { id, parent }));
1794         self.push_iter(clips);
1795         id
1796     }
1797 
define_clip_image_mask( &mut self, parent_space_and_clip: &di::SpaceAndClipInfo, image_mask: di::ImageMask, points: &[LayoutPoint], fill_rule: di::FillRule, ) -> di::ClipId1798     pub fn define_clip_image_mask(
1799         &mut self,
1800         parent_space_and_clip: &di::SpaceAndClipInfo,
1801         image_mask: di::ImageMask,
1802         points: &[LayoutPoint],
1803         fill_rule: di::FillRule,
1804     ) -> di::ClipId {
1805         let id = self.generate_clip_index();
1806         let item = di::DisplayItem::ImageMaskClip(di::ImageMaskClipDisplayItem {
1807             id,
1808             parent_space_and_clip: *parent_space_and_clip,
1809             image_mask,
1810             fill_rule,
1811         });
1812 
1813         // We only need to supply points if there are at least 3, which is the
1814         // minimum to specify a polygon. BuiltDisplayListIter.next ensures that points
1815         // are cleared between processing other display items, so we'll correctly get
1816         // zero points when no SetPoints item has been pushed.
1817         if points.len() >= 3 {
1818             self.push_item(&di::DisplayItem::SetPoints);
1819             self.push_iter(points);
1820         }
1821         self.push_item(&item);
1822         id
1823     }
1824 
define_clip_rect( &mut self, parent_space_and_clip: &di::SpaceAndClipInfo, clip_rect: LayoutRect, ) -> di::ClipId1825     pub fn define_clip_rect(
1826         &mut self,
1827         parent_space_and_clip: &di::SpaceAndClipInfo,
1828         clip_rect: LayoutRect,
1829     ) -> di::ClipId {
1830         let id = self.generate_clip_index();
1831         let item = di::DisplayItem::RectClip(di::RectClipDisplayItem {
1832             id,
1833             parent_space_and_clip: *parent_space_and_clip,
1834             clip_rect,
1835         });
1836 
1837         self.push_item(&item);
1838         id
1839     }
1840 
define_clip_rounded_rect( &mut self, parent_space_and_clip: &di::SpaceAndClipInfo, clip: di::ComplexClipRegion, ) -> di::ClipId1841     pub fn define_clip_rounded_rect(
1842         &mut self,
1843         parent_space_and_clip: &di::SpaceAndClipInfo,
1844         clip: di::ComplexClipRegion,
1845     ) -> di::ClipId {
1846         let id = self.generate_clip_index();
1847         let item = di::DisplayItem::RoundedRectClip(di::RoundedRectClipDisplayItem {
1848             id,
1849             parent_space_and_clip: *parent_space_and_clip,
1850             clip,
1851         });
1852 
1853         self.push_item(&item);
1854         id
1855     }
1856 
define_sticky_frame( &mut self, parent_spatial_id: di::SpatialId, frame_rect: LayoutRect, margins: SideOffsets2D<Option<f32>, LayoutPixel>, vertical_offset_bounds: di::StickyOffsetBounds, horizontal_offset_bounds: di::StickyOffsetBounds, previously_applied_offset: LayoutVector2D, ) -> di::SpatialId1857     pub fn define_sticky_frame(
1858         &mut self,
1859         parent_spatial_id: di::SpatialId,
1860         frame_rect: LayoutRect,
1861         margins: SideOffsets2D<Option<f32>, LayoutPixel>,
1862         vertical_offset_bounds: di::StickyOffsetBounds,
1863         horizontal_offset_bounds: di::StickyOffsetBounds,
1864         previously_applied_offset: LayoutVector2D,
1865     ) -> di::SpatialId {
1866         let id = self.generate_spatial_index();
1867         let item = di::DisplayItem::StickyFrame(di::StickyFrameDisplayItem {
1868             parent_spatial_id,
1869             id,
1870             bounds: frame_rect,
1871             margins,
1872             vertical_offset_bounds,
1873             horizontal_offset_bounds,
1874             previously_applied_offset,
1875         });
1876 
1877         self.push_item(&item);
1878         id
1879     }
1880 
push_iframe( &mut self, bounds: LayoutRect, clip_rect: LayoutRect, space_and_clip: &di::SpaceAndClipInfo, pipeline_id: PipelineId, ignore_missing_pipeline: bool )1881     pub fn push_iframe(
1882         &mut self,
1883         bounds: LayoutRect,
1884         clip_rect: LayoutRect,
1885         space_and_clip: &di::SpaceAndClipInfo,
1886         pipeline_id: PipelineId,
1887         ignore_missing_pipeline: bool
1888     ) {
1889         let item = di::DisplayItem::Iframe(di::IframeDisplayItem {
1890             bounds,
1891             clip_rect,
1892             space_and_clip: *space_and_clip,
1893             pipeline_id,
1894             ignore_missing_pipeline,
1895         });
1896         self.push_item(&item);
1897     }
1898 
push_shadow( &mut self, space_and_clip: &di::SpaceAndClipInfo, shadow: di::Shadow, should_inflate: bool, )1899     pub fn push_shadow(
1900         &mut self,
1901         space_and_clip: &di::SpaceAndClipInfo,
1902         shadow: di::Shadow,
1903         should_inflate: bool,
1904     ) {
1905         let item = di::DisplayItem::PushShadow(di::PushShadowDisplayItem {
1906             space_and_clip: *space_and_clip,
1907             shadow,
1908             should_inflate,
1909         });
1910         self.push_item(&item);
1911     }
1912 
pop_all_shadows(&mut self)1913     pub fn pop_all_shadows(&mut self) {
1914         self.push_item(&di::DisplayItem::PopAllShadows);
1915     }
1916 
start_item_group(&mut self)1917     pub fn start_item_group(&mut self) {
1918         debug_assert!(!self.writing_to_chunk);
1919         debug_assert!(self.pending_chunk.is_empty());
1920 
1921         self.writing_to_chunk = true;
1922     }
1923 
flush_pending_item_group(&mut self, key: di::ItemKey)1924     fn flush_pending_item_group(&mut self, key: di::ItemKey) {
1925         // Push RetainedItems-marker to extra_data section.
1926         self.push_retained_items(key);
1927 
1928         // Push pending chunk to extra_data section.
1929         self.extra_data.append(&mut self.pending_chunk);
1930 
1931         // Push ReuseItems-marker to data section.
1932         self.push_reuse_items(key);
1933     }
1934 
finish_item_group(&mut self, key: di::ItemKey) -> bool1935     pub fn finish_item_group(&mut self, key: di::ItemKey) -> bool {
1936         debug_assert!(self.writing_to_chunk);
1937         self.writing_to_chunk = false;
1938 
1939         if self.pending_chunk.is_empty() {
1940             return false;
1941         }
1942 
1943         self.flush_pending_item_group(key);
1944         true
1945     }
1946 
cancel_item_group(&mut self, discard: bool)1947     pub fn cancel_item_group(&mut self, discard: bool) {
1948         debug_assert!(self.writing_to_chunk);
1949         self.writing_to_chunk = false;
1950 
1951         if discard {
1952             self.pending_chunk.clear();
1953         } else {
1954             // Push pending chunk to data section.
1955             self.data.append(&mut self.pending_chunk);
1956         }
1957     }
1958 
push_reuse_items(&mut self, key: di::ItemKey)1959     pub fn push_reuse_items(&mut self, key: di::ItemKey) {
1960         self.push_item_to_section(
1961             &di::DisplayItem::ReuseItems(key),
1962             DisplayListSection::Data
1963         );
1964     }
1965 
push_retained_items(&mut self, key: di::ItemKey)1966     fn push_retained_items(&mut self, key: di::ItemKey) {
1967         self.push_item_to_section(
1968             &di::DisplayItem::RetainedItems(key),
1969             DisplayListSection::ExtraData
1970         );
1971     }
1972 
set_cache_size(&mut self, cache_size: usize)1973     pub fn set_cache_size(&mut self, cache_size: usize) {
1974         self.cache_size = cache_size;
1975     }
1976 
finalize(mut self) -> (PipelineId, BuiltDisplayList)1977     pub fn finalize(mut self) -> (PipelineId, BuiltDisplayList) {
1978         assert!(self.save_state.is_none(), "Finalized DisplayListBuilder with a pending save");
1979 
1980         if let Some(content) = self.serialized_content_buffer.take() {
1981             println!("-- WebRender display list for {:?} --\n{}",
1982                 self.pipeline_id, content);
1983         }
1984 
1985         // Add `DisplayItem::max_size` zone of zeroes to the end of display list
1986         // so there is at least this amount available in the display list during
1987         // serialization.
1988         ensure_red_zone::<di::DisplayItem>(&mut self.data);
1989 
1990         let extra_data_offset = self.data.len();
1991 
1992         if self.extra_data.len() > 0 {
1993             ensure_red_zone::<di::DisplayItem>(&mut self.extra_data);
1994             self.data.extend(self.extra_data);
1995         }
1996 
1997         let end_time = precise_time_ns();
1998         (
1999             self.pipeline_id,
2000             BuiltDisplayList {
2001                 descriptor: BuiltDisplayListDescriptor {
2002                     gecko_display_list_type: GeckoDisplayListType::None,
2003                     builder_start_time: self.builder_start_time,
2004                     builder_finish_time: end_time,
2005                     send_start_time: end_time,
2006                     total_clip_nodes: self.next_clip_index,
2007                     total_spatial_nodes: self.next_spatial_index,
2008                     cache_size: self.cache_size,
2009                     extra_data_offset,
2010                 },
2011                 data: self.data,
2012             },
2013         )
2014     }
2015 }
2016