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