1use euclid::SideOffsets2D;
6use peek_poke::{ensure_red_zone, peek_from_slice, poke_extend_vec, strip_red_zone};
7use peek_poke::{poke_inplace_slice, poke_into_vec, Poke};
8#[cfg(feature = "deserialize")]
9use serde::de::Deserializer;
10#[cfg(feature = "serialize")]
11use serde::ser::Serializer;
12use serde::{Deserialize, Serialize};
13use std::io::Write;
14use std::marker::PhantomData;
15use std::ops::Range;
16use std::mem;
17use std::collections::HashMap;
18use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
19use crate::display_item as di;
21use crate::display_item_cache::*;
22use crate::{APZScrollGeneration, HasScrollLinkedEffect, PipelineId, PropertyBinding};
23use crate::gradient_builder::GradientBuilder;
24use crate::color::ColorF;
25use crate::font::{FontInstanceKey, GlyphInstance, GlyphOptions};
26use crate::image::{ColorDepth, ImageKey};
27use crate::precise_time_ns;
28use crate::units::*;
29
30
31pub const MAX_TEXT_RUN_LENGTH: usize = 2040;
34
35const FIRST_SPATIAL_NODE_INDEX: usize = 2;
39
40const FIRST_CLIP_NODE_INDEX: usize = 1;
42
43#[derive(Debug, Copy, Clone, PartialEq)]
44enum BuildState {
45 Idle,
46 Build,
47}
48
49#[repr(C)]
50#[derive(Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
51pub struct ItemRange<'a, T> {
52 bytes: &'a [u8],
53 _boo: PhantomData<T>,
54}
55
56impl<'a, T> Copy for ItemRange<'a, T> {}
57impl<'a, T> Clone for ItemRange<'a, T> {
58 fn clone(&self) -> Self {
59 *self
60 }
61}
62
63impl<'a, T> Default for ItemRange<'a, T> {
64 fn default() -> Self {
65 ItemRange {
66 bytes: Default::default(),
67 _boo: PhantomData,
68 }
69 }
70}
71
72impl<'a, T> ItemRange<'a, T> {
73 pub fn new(bytes: &'a [u8]) -> Self {
74 Self {
75 bytes,
76 _boo: PhantomData
77 }
78 }
79
80 pub fn is_empty(&self) -> bool {
81 self.bytes.len() <= mem::size_of::<usize>()
83 }
84
85 pub fn bytes(&self) -> &[u8] {
86 self.bytes
87 }
88}
89
90impl<'a, T: Default> ItemRange<'a, T> {
91 pub fn iter(&self) -> AuxIter<'a, T> {
92 AuxIter::new(T::default(), self.bytes)
93 }
94}
95
96impl<'a, T> IntoIterator for ItemRange<'a, T>
97where
98 T: Copy + Default + peek_poke::Peek,
99{
100 type Item = T;
101 type IntoIter = AuxIter<'a, T>;
102 fn into_iter(self) -> Self::IntoIter {
103 self.iter()
104 }
105}
106
107#[derive(Copy, Clone)]
108pub struct TempFilterData<'a> {
109 pub func_types: ItemRange<'a, di::ComponentTransferFuncType>,
110 pub r_values: ItemRange<'a, f32>,
111 pub g_values: ItemRange<'a, f32>,
112 pub b_values: ItemRange<'a, f32>,
113 pub a_values: ItemRange<'a, f32>,
114}
115
116#[derive(Default, Clone)]
117pub struct DisplayListPayload {
118 pub items_data: Vec<u8>,
120
121 pub cache_data: Vec<u8>,
123
124 pub spatial_tree: Vec<u8>,
126}
127
128impl DisplayListPayload {
129 fn default() -> Self {
130 DisplayListPayload {
131 items_data: Vec::new(),
132 cache_data: Vec::new(),
133 spatial_tree: Vec::new(),
134 }
135 }
136
137 fn new(capacity: DisplayListCapacity) -> Self {
138 let mut payload = Self::default();
139
140 if payload.items_data.try_reserve(capacity.items_size).is_err() {
144 return Self::default();
145 }
146 if payload.cache_data.try_reserve(capacity.cache_size).is_err() {
147 return Self::default();
148 }
149 if payload.spatial_tree.try_reserve(capacity.spatial_tree_size).is_err() {
150 return Self::default();
151 }
152 payload
153 }
154
155 fn clear(&mut self) {
156 self.items_data.clear();
157 self.cache_data.clear();
158 self.spatial_tree.clear();
159 }
160
161 fn size_in_bytes(&self) -> usize {
162 self.items_data.len() +
163 self.cache_data.len() +
164 self.spatial_tree.len()
165 }
166
167 #[cfg(feature = "serialize")]
168 fn create_debug_spatial_tree_items(&self) -> Vec<di::SpatialTreeItem> {
169 let mut items = Vec::new();
170
171 iter_spatial_tree(&self.spatial_tree, |item| {
172 items.push(*item);
173 });
174
175 items
176 }
177}
178
179impl MallocSizeOf for DisplayListPayload {
180 fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
181 self.items_data.size_of(ops) +
182 self.cache_data.size_of(ops) +
183 self.spatial_tree.size_of(ops)
184 }
185}
186
187#[derive(Default, Clone)]
189pub struct BuiltDisplayList {
190 payload: DisplayListPayload,
191 descriptor: BuiltDisplayListDescriptor,
192}
193
194#[repr(C)]
195#[derive(Copy, Clone, Default, Deserialize, Serialize)]
196pub enum GeckoDisplayListType {
197 #[default]
198 None,
199 Partial(f64),
200 Full(f64),
201}
202
203#[repr(C)]
208#[derive(Copy, Clone, Default, Deserialize, Serialize)]
209pub struct BuiltDisplayListDescriptor {
210 gecko_display_list_type: GeckoDisplayListType,
212 builder_start_time: u64,
214 builder_finish_time: u64,
216 send_start_time: u64,
218 total_clip_nodes: usize,
220 total_spatial_nodes: usize,
222 cache_size: usize,
224}
225
226#[derive(Clone)]
227pub struct DisplayListWithCache {
228 pub display_list: BuiltDisplayList,
229 cache: DisplayItemCache,
230}
231
232impl DisplayListWithCache {
233 pub fn iter(&self) -> BuiltDisplayListIter {
234 self.display_list.iter_with_cache(&self.cache)
235 }
236
237 pub fn new_from_list(display_list: BuiltDisplayList) -> Self {
238 let mut cache = DisplayItemCache::new();
239 cache.update(&display_list);
240
241 DisplayListWithCache {
242 display_list,
243 cache
244 }
245 }
246
247 pub fn update(&mut self, display_list: BuiltDisplayList) {
248 self.cache.update(&display_list);
249 self.display_list = display_list;
250 }
251
252 pub fn descriptor(&self) -> &BuiltDisplayListDescriptor {
253 self.display_list.descriptor()
254 }
255
256 pub fn times(&self) -> (u64, u64, u64) {
257 self.display_list.times()
258 }
259
260 pub fn items_data(&self) -> &[u8] {
261 self.display_list.items_data()
262 }
263}
264
265impl MallocSizeOf for DisplayListWithCache {
266 fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
267 self.display_list.payload.size_of(ops) + self.cache.size_of(ops)
268 }
269}
270
271#[cfg(any(feature = "serialize", feature = "deserialize"))]
274#[cfg_attr(feature = "serialize", derive(Serialize))]
275#[cfg_attr(feature = "deserialize", derive(Deserialize))]
276struct DisplayListCapture {
277 display_items: Vec<di::DebugDisplayItem>,
278 spatial_tree_items: Vec<di::SpatialTreeItem>,
279 descriptor: BuiltDisplayListDescriptor,
280}
281
282#[cfg(feature = "serialize")]
283impl Serialize for DisplayListWithCache {
284 fn serialize<S: Serializer>(
285 &self,
286 serializer: S
287 ) -> Result<S::Ok, S::Error> {
288 let display_items = BuiltDisplayList::create_debug_display_items(self.iter());
289 let spatial_tree_items = self.display_list.payload.create_debug_spatial_tree_items();
290
291 let dl = DisplayListCapture {
292 display_items,
293 spatial_tree_items,
294 descriptor: self.display_list.descriptor,
295 };
296
297 dl.serialize(serializer)
298 }
299}
300
301#[cfg(feature = "deserialize")]
302impl<'de> Deserialize<'de> for DisplayListWithCache {
303 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
304 where
305 D: Deserializer<'de>,
306 {
307 use crate::display_item::DisplayItem as Real;
308 use crate::display_item::DebugDisplayItem as Debug;
309
310 let capture = DisplayListCapture::deserialize(deserializer)?;
311
312 let mut spatial_tree = Vec::new();
313 for item in capture.spatial_tree_items {
314 poke_into_vec(&item, &mut spatial_tree);
315 }
316 ensure_red_zone::<di::SpatialTreeItem>(&mut spatial_tree);
317
318 let mut items_data = Vec::new();
319 let mut temp = Vec::new();
320 for complete in capture.display_items {
321 let item = match complete {
322 Debug::ClipChain(v, clip_chain_ids) => {
323 DisplayListBuilder::push_iter_impl(&mut temp, clip_chain_ids);
324 Real::ClipChain(v)
325 }
326 Debug::Text(v, glyphs) => {
327 DisplayListBuilder::push_iter_impl(&mut temp, glyphs);
328 Real::Text(v)
329 },
330 Debug::Iframe(v) => {
331 Real::Iframe(v)
332 }
333 Debug::PushReferenceFrame(v) => {
334 Real::PushReferenceFrame(v)
335 }
336 Debug::SetFilterOps(filters) => {
337 DisplayListBuilder::push_iter_impl(&mut temp, filters);
338 Real::SetFilterOps
339 },
340 Debug::SetFilterData(filter_data) => {
341 let func_types: Vec<di::ComponentTransferFuncType> =
342 [filter_data.func_r_type,
343 filter_data.func_g_type,
344 filter_data.func_b_type,
345 filter_data.func_a_type].to_vec();
346 DisplayListBuilder::push_iter_impl(&mut temp, func_types);
347 DisplayListBuilder::push_iter_impl(&mut temp, filter_data.r_values);
348 DisplayListBuilder::push_iter_impl(&mut temp, filter_data.g_values);
349 DisplayListBuilder::push_iter_impl(&mut temp, filter_data.b_values);
350 DisplayListBuilder::push_iter_impl(&mut temp, filter_data.a_values);
351 Real::SetFilterData
352 },
353 Debug::SetFilterPrimitives(filter_primitives) => {
354 DisplayListBuilder::push_iter_impl(&mut temp, filter_primitives);
355 Real::SetFilterPrimitives
356 }
357 Debug::SetGradientStops(stops) => {
358 DisplayListBuilder::push_iter_impl(&mut temp, stops);
359 Real::SetGradientStops
360 },
361 Debug::SetPoints(points) => {
362 DisplayListBuilder::push_iter_impl(&mut temp, points);
363 Real::SetPoints
364 },
365 Debug::RectClip(v) => Real::RectClip(v),
366 Debug::RoundedRectClip(v) => Real::RoundedRectClip(v),
367 Debug::ImageMaskClip(v) => Real::ImageMaskClip(v),
368 Debug::Rectangle(v) => Real::Rectangle(v),
369 Debug::ClearRectangle(v) => Real::ClearRectangle(v),
370 Debug::HitTest(v) => Real::HitTest(v),
371 Debug::Line(v) => Real::Line(v),
372 Debug::Image(v) => Real::Image(v),
373 Debug::RepeatingImage(v) => Real::RepeatingImage(v),
374 Debug::YuvImage(v) => Real::YuvImage(v),
375 Debug::Border(v) => Real::Border(v),
376 Debug::BoxShadow(v) => Real::BoxShadow(v),
377 Debug::Gradient(v) => Real::Gradient(v),
378 Debug::RadialGradient(v) => Real::RadialGradient(v),
379 Debug::ConicGradient(v) => Real::ConicGradient(v),
380 Debug::PushStackingContext(v) => Real::PushStackingContext(v),
381 Debug::PushShadow(v) => Real::PushShadow(v),
382 Debug::BackdropFilter(v) => Real::BackdropFilter(v),
383
384 Debug::PopStackingContext => Real::PopStackingContext,
385 Debug::PopReferenceFrame => Real::PopReferenceFrame,
386 Debug::PopAllShadows => Real::PopAllShadows,
387 Debug::DebugMarker(val) => Real::DebugMarker(val),
388 };
389 poke_into_vec(&item, &mut items_data);
390 items_data.extend(temp.drain(..));
392 }
393
394 ensure_red_zone::<di::DisplayItem>(&mut items_data);
398
399 Ok(DisplayListWithCache {
400 display_list: BuiltDisplayList {
401 descriptor: capture.descriptor,
402 payload: DisplayListPayload {
403 cache_data: Vec::new(),
404 items_data,
405 spatial_tree,
406 },
407 },
408 cache: DisplayItemCache::new(),
409 })
410 }
411}
412
413pub struct BuiltDisplayListIter<'a> {
414 data: &'a [u8],
415 cache: Option<&'a DisplayItemCache>,
416 pending_items: std::slice::Iter<'a, CachedDisplayItem>,
417 cur_cached_item: Option<&'a CachedDisplayItem>,
418 cur_item: di::DisplayItem,
419 cur_stops: ItemRange<'a, di::GradientStop>,
420 cur_glyphs: ItemRange<'a, GlyphInstance>,
421 cur_filters: ItemRange<'a, di::FilterOp>,
422 cur_filter_data: Vec<TempFilterData<'a>>,
423 cur_filter_primitives: ItemRange<'a, di::FilterPrimitive>,
424 cur_clip_chain_items: ItemRange<'a, di::ClipId>,
425 cur_points: ItemRange<'a, LayoutPoint>,
426 peeking: Peek,
427 debug_stats: DebugStats,
429}
430
431#[allow(dead_code)]
433struct DebugStats {
434 last_addr: usize,
436 stats: HashMap<&'static str, ItemStats>,
437}
438
439impl DebugStats {
440 #[cfg(feature = "display_list_stats")]
441 fn _update_entry(&mut self, name: &'static str, item_count: usize, byte_count: usize) {
442 let entry = self.stats.entry(name).or_default();
443 entry.total_count += item_count;
444 entry.num_bytes += byte_count;
445 }
446
447 #[cfg(feature = "display_list_stats")]
450 fn debug_num_bytes(&mut self, data: &[u8]) -> usize {
451 let old_addr = self.last_addr;
452 let new_addr = data.as_ptr() as usize;
453 let delta = new_addr - old_addr;
454 self.last_addr = new_addr;
455
456 delta
457 }
458
459 #[cfg(feature = "display_list_stats")]
461 fn log_item(&mut self, data: &[u8], item: &di::DisplayItem) {
462 let num_bytes = self.debug_num_bytes(data);
463 self._update_entry(item.debug_name(), 1, num_bytes);
464 }
465
466 #[cfg(feature = "display_list_stats")]
468 fn log_slice<T: Copy + Default + peek_poke::Peek>(
469 &mut self,
470 slice_name: &'static str,
471 range: &ItemRange<T>,
472 ) {
473 self.last_addr = range.bytes.as_ptr() as usize + range.bytes.len();
477
478 self._update_entry(slice_name, range.iter().len(), range.bytes.len());
479 }
480
481 #[cfg(not(feature = "display_list_stats"))]
482 fn log_slice<T>(&mut self, _slice_name: &str, _range: &ItemRange<T>) {
483 }
485}
486
487#[derive(Copy, Clone, Debug, Default)]
489pub struct ItemStats {
490 pub total_count: usize,
492 pub num_bytes: usize,
494}
495
496pub struct DisplayItemRef<'a: 'b, 'b> {
497 iter: &'b BuiltDisplayListIter<'a>,
498}
499
500impl<'a, 'b> DisplayItemRef<'a, 'b> {
502 pub fn sub_iter(&self) -> BuiltDisplayListIter<'a> {
504 self.iter.sub_iter()
505 }
506
507 pub fn item(&self) -> &di::DisplayItem {
508 self.iter.current_item()
509 }
510
511 pub fn clip_chain_items(&self) -> ItemRange<di::ClipId> {
512 self.iter.cur_clip_chain_items
513 }
514
515 pub fn points(&self) -> ItemRange<LayoutPoint> {
516 self.iter.cur_points
517 }
518
519 pub fn glyphs(&self) -> ItemRange<GlyphInstance> {
520 self.iter.glyphs()
521 }
522
523 pub fn gradient_stops(&self) -> ItemRange<di::GradientStop> {
524 self.iter.gradient_stops()
525 }
526
527 pub fn filters(&self) -> ItemRange<di::FilterOp> {
528 self.iter.cur_filters
529 }
530
531 pub fn filter_datas(&self) -> &Vec<TempFilterData> {
532 &self.iter.cur_filter_data
533 }
534
535 pub fn filter_primitives(&self) -> ItemRange<di::FilterPrimitive> {
536 self.iter.cur_filter_primitives
537 }
538}
539
540#[derive(PartialEq)]
541enum Peek {
542 StartPeeking,
543 IsPeeking,
544 NotPeeking,
545}
546
547#[derive(Clone)]
548pub struct AuxIter<'a, T> {
549 item: T,
550 data: &'a [u8],
551 size: usize,
552}
554
555impl BuiltDisplayList {
556 pub fn from_data(
557 payload: DisplayListPayload,
558 descriptor: BuiltDisplayListDescriptor,
559 ) -> Self {
560 BuiltDisplayList {
561 payload,
562 descriptor,
563 }
564 }
565
566 pub fn into_data(self) -> (DisplayListPayload, BuiltDisplayListDescriptor) {
567 (self.payload, self.descriptor)
568 }
569
570 pub fn items_data(&self) -> &[u8] {
571 &self.payload.items_data
572 }
573
574 pub fn cache_data(&self) -> &[u8] {
575 &self.payload.cache_data
576 }
577
578 pub fn descriptor(&self) -> &BuiltDisplayListDescriptor {
579 &self.descriptor
580 }
581
582 pub fn set_send_time_ns(&mut self, time: u64) {
583 self.descriptor.send_start_time = time;
584 }
585
586 pub fn times(&self) -> (u64, u64, u64) {
587 (
588 self.descriptor.builder_start_time,
589 self.descriptor.builder_finish_time,
590 self.descriptor.send_start_time,
591 )
592 }
593
594 pub fn gecko_display_list_stats(&self) -> (f64, bool) {
595 match self.descriptor.gecko_display_list_type {
596 GeckoDisplayListType::Full(duration) => (duration, true),
597 GeckoDisplayListType::Partial(duration) => (duration, false),
598 _ => (0.0, false)
599 }
600 }
601
602 pub fn total_clip_nodes(&self) -> usize {
603 self.descriptor.total_clip_nodes
604 }
605
606 pub fn total_spatial_nodes(&self) -> usize {
607 self.descriptor.total_spatial_nodes
608 }
609
610 pub fn iter(&self) -> BuiltDisplayListIter {
611 BuiltDisplayListIter::new(self.items_data(), None)
612 }
613
614 pub fn cache_data_iter(&self) -> BuiltDisplayListIter {
615 BuiltDisplayListIter::new(self.cache_data(), None)
616 }
617
618 pub fn iter_with_cache<'a>(
619 &'a self,
620 cache: &'a DisplayItemCache
621 ) -> BuiltDisplayListIter<'a> {
622 BuiltDisplayListIter::new(self.items_data(), Some(cache))
623 }
624
625 pub fn cache_size(&self) -> usize {
626 self.descriptor.cache_size
627 }
628
629 pub fn size_in_bytes(&self) -> usize {
630 self.payload.size_in_bytes()
631 }
632
633 pub fn iter_spatial_tree<F>(&self, f: F) where F: FnMut(&di::SpatialTreeItem) {
634 iter_spatial_tree(&self.payload.spatial_tree, f)
635 }
636
637 #[cfg(feature = "serialize")]
638 pub fn create_debug_display_items(
639 mut iterator: BuiltDisplayListIter,
640 ) -> Vec<di::DebugDisplayItem> {
641 use di::DisplayItem as Real;
642 use di::DebugDisplayItem as Debug;
643 let mut debug_items = Vec::new();
644
645 while let Some(item) = iterator.next_raw() {
646 let serial_di = match *item.item() {
647 Real::ClipChain(v) => Debug::ClipChain(
648 v,
649 item.iter.cur_clip_chain_items.iter().collect()
650 ),
651 Real::Text(v) => Debug::Text(
652 v,
653 item.iter.cur_glyphs.iter().collect()
654 ),
655 Real::SetFilterOps => Debug::SetFilterOps(
656 item.iter.cur_filters.iter().collect()
657 ),
658 Real::SetFilterData => {
659 debug_assert!(!item.iter.cur_filter_data.is_empty(),
660 "next_raw should have populated cur_filter_data");
661 let temp_filter_data = &item.iter.cur_filter_data[item.iter.cur_filter_data.len()-1];
662
663 let func_types: Vec<di::ComponentTransferFuncType> =
664 temp_filter_data.func_types.iter().collect();
665 debug_assert!(func_types.len() == 4,
666 "someone changed the number of filter funcs without updating this code");
667 Debug::SetFilterData(di::FilterData {
668 func_r_type: func_types[0],
669 r_values: temp_filter_data.r_values.iter().collect(),
670 func_g_type: func_types[1],
671 g_values: temp_filter_data.g_values.iter().collect(),
672 func_b_type: func_types[2],
673 b_values: temp_filter_data.b_values.iter().collect(),
674 func_a_type: func_types[3],
675 a_values: temp_filter_data.a_values.iter().collect(),
676 })
677 },
678 Real::SetFilterPrimitives => Debug::SetFilterPrimitives(
679 item.iter.cur_filter_primitives.iter().collect()
680 ),
681 Real::SetGradientStops => Debug::SetGradientStops(
682 item.iter.cur_stops.iter().collect()
683 ),
684 Real::SetPoints => Debug::SetPoints(
685 item.iter.cur_points.iter().collect()
686 ),
687 Real::RectClip(v) => Debug::RectClip(v),
688 Real::RoundedRectClip(v) => Debug::RoundedRectClip(v),
689 Real::ImageMaskClip(v) => Debug::ImageMaskClip(v),
690 Real::Rectangle(v) => Debug::Rectangle(v),
691 Real::ClearRectangle(v) => Debug::ClearRectangle(v),
692 Real::HitTest(v) => Debug::HitTest(v),
693 Real::Line(v) => Debug::Line(v),
694 Real::Image(v) => Debug::Image(v),
695 Real::RepeatingImage(v) => Debug::RepeatingImage(v),
696 Real::YuvImage(v) => Debug::YuvImage(v),
697 Real::Border(v) => Debug::Border(v),
698 Real::BoxShadow(v) => Debug::BoxShadow(v),
699 Real::Gradient(v) => Debug::Gradient(v),
700 Real::RadialGradient(v) => Debug::RadialGradient(v),
701 Real::ConicGradient(v) => Debug::ConicGradient(v),
702 Real::Iframe(v) => Debug::Iframe(v),
703 Real::PushReferenceFrame(v) => Debug::PushReferenceFrame(v),
704 Real::PushStackingContext(v) => Debug::PushStackingContext(v),
705 Real::PushShadow(v) => Debug::PushShadow(v),
706 Real::BackdropFilter(v) => Debug::BackdropFilter(v),
707
708 Real::PopReferenceFrame => Debug::PopReferenceFrame,
709 Real::PopStackingContext => Debug::PopStackingContext,
710 Real::PopAllShadows => Debug::PopAllShadows,
711 Real::ReuseItems(_) |
712 Real::RetainedItems(_) => unreachable!("Unexpected item"),
713 Real::DebugMarker(val) => Debug::DebugMarker(val),
714 };
715 debug_items.push(serial_di);
716 }
717
718 debug_items
719 }
720}
721
722fn skip_slice<'a, T: peek_poke::Peek>(data: &mut &'a [u8]) -> ItemRange<'a, T> {
724 let mut skip_offset = 0usize;
725 *data = peek_from_slice(data, &mut skip_offset);
726 let (skip, rest) = data.split_at(skip_offset);
727
728 *data = rest;
730
731 ItemRange {
732 bytes: skip,
733 _boo: PhantomData,
734 }
735}
736
737impl<'a> BuiltDisplayListIter<'a> {
738 pub fn new(
739 data: &'a [u8],
740 cache: Option<&'a DisplayItemCache>,
741 ) -> Self {
742 Self {
743 data,
744 cache,
745 pending_items: [].iter(),
746 cur_cached_item: None,
747 cur_item: di::DisplayItem::PopStackingContext,
748 cur_stops: ItemRange::default(),
749 cur_glyphs: ItemRange::default(),
750 cur_filters: ItemRange::default(),
751 cur_filter_data: Vec::new(),
752 cur_filter_primitives: ItemRange::default(),
753 cur_clip_chain_items: ItemRange::default(),
754 cur_points: ItemRange::default(),
755 peeking: Peek::NotPeeking,
756 debug_stats: DebugStats {
757 last_addr: data.as_ptr() as usize,
758 stats: HashMap::default(),
759 },
760 }
761 }
762
763 pub fn sub_iter(&self) -> Self {
764 let mut iter = BuiltDisplayListIter::new(
765 self.data, self.cache
766 );
767 iter.pending_items = self.pending_items.clone();
768 iter
769 }
770
771 pub fn current_item(&self) -> &di::DisplayItem {
772 match self.cur_cached_item {
773 Some(cached_item) => cached_item.display_item(),
774 None => &self.cur_item
775 }
776 }
777
778 fn cached_item_range_or<T>(
779 &self,
780 data: ItemRange<'a, T>
781 ) -> ItemRange<'a, T> {
782 match self.cur_cached_item {
783 Some(cached_item) => cached_item.data_as_item_range(),
784 None => data,
785 }
786 }
787
788 pub fn glyphs(&self) -> ItemRange<GlyphInstance> {
789 self.cached_item_range_or(self.cur_glyphs)
790 }
791
792 pub fn gradient_stops(&self) -> ItemRange<di::GradientStop> {
793 self.cached_item_range_or(self.cur_stops)
794 }
795
796 fn advance_pending_items(&mut self) -> bool {
797 self.cur_cached_item = self.pending_items.next();
798 self.cur_cached_item.is_some()
799 }
800
801 pub fn next<'b>(&'b mut self) -> Option<DisplayItemRef<'a, 'b>> {
802 use crate::DisplayItem::*;
803
804 match self.peeking {
805 Peek::IsPeeking => {
806 self.peeking = Peek::NotPeeking;
807 return Some(self.as_ref());
808 }
809 Peek::StartPeeking => {
810 self.peeking = Peek::IsPeeking;
811 }
812 Peek::NotPeeking => { }
813 }
814
815 self.cur_stops = ItemRange::default();
817 self.cur_clip_chain_items = ItemRange::default();
818 self.cur_points = ItemRange::default();
819 self.cur_filters = ItemRange::default();
820 self.cur_filter_primitives = ItemRange::default();
821 self.cur_filter_data.clear();
822
823 loop {
824 self.next_raw()?;
825 match self.cur_item {
826 SetGradientStops |
827 SetFilterOps |
828 SetFilterData |
829 SetFilterPrimitives |
830 SetPoints => {
831 continue;
833 }
834 _ => {
835 break;
836 }
837 }
838 }
839
840 Some(self.as_ref())
841 }
842
843 pub fn next_raw<'b>(&'b mut self) -> Option<DisplayItemRef<'a, 'b>> {
847 use crate::DisplayItem::*;
848
849 if self.advance_pending_items() {
850 return Some(self.as_ref());
851 }
852
853 if self.data.len() <= di::DisplayItem::max_size() {
857 return None;
858 }
859
860 self.data = peek_from_slice(self.data, &mut self.cur_item);
861 self.log_item_stats();
862
863 match self.cur_item {
864 SetGradientStops => {
865 self.cur_stops = skip_slice::<di::GradientStop>(&mut self.data);
866 self.debug_stats.log_slice("set_gradient_stops.stops", &self.cur_stops);
867 }
868 SetFilterOps => {
869 self.cur_filters = skip_slice::<di::FilterOp>(&mut self.data);
870 self.debug_stats.log_slice("set_filter_ops.ops", &self.cur_filters);
871 }
872 SetFilterData => {
873 self.cur_filter_data.push(TempFilterData {
874 func_types: skip_slice::<di::ComponentTransferFuncType>(&mut self.data),
875 r_values: skip_slice::<f32>(&mut self.data),
876 g_values: skip_slice::<f32>(&mut self.data),
877 b_values: skip_slice::<f32>(&mut self.data),
878 a_values: skip_slice::<f32>(&mut self.data),
879 });
880
881 let data = *self.cur_filter_data.last().unwrap();
882 self.debug_stats.log_slice("set_filter_data.func_types", &data.func_types);
883 self.debug_stats.log_slice("set_filter_data.r_values", &data.r_values);
884 self.debug_stats.log_slice("set_filter_data.g_values", &data.g_values);
885 self.debug_stats.log_slice("set_filter_data.b_values", &data.b_values);
886 self.debug_stats.log_slice("set_filter_data.a_values", &data.a_values);
887 }
888 SetFilterPrimitives => {
889 self.cur_filter_primitives = skip_slice::<di::FilterPrimitive>(&mut self.data);
890 self.debug_stats.log_slice("set_filter_primitives.primitives", &self.cur_filter_primitives);
891 }
892 SetPoints => {
893 self.cur_points = skip_slice::<LayoutPoint>(&mut self.data);
894 self.debug_stats.log_slice("set_points.points", &self.cur_points);
895 }
896 ClipChain(_) => {
897 self.cur_clip_chain_items = skip_slice::<di::ClipId>(&mut self.data);
898 self.debug_stats.log_slice("clip_chain.clip_ids", &self.cur_clip_chain_items);
899 }
900 Text(_) => {
901 self.cur_glyphs = skip_slice::<GlyphInstance>(&mut self.data);
902 self.debug_stats.log_slice("text.glyphs", &self.cur_glyphs);
903 }
904 ReuseItems(key) => {
905 match self.cache {
906 Some(cache) => {
907 self.pending_items = cache.get_items(key).iter();
908 self.advance_pending_items();
909 }
910 None => {
911 unreachable!("Cache marker without cache!");
912 }
913 }
914 }
915 _ => { }
916 }
917
918 Some(self.as_ref())
919 }
920
921 pub fn as_ref<'b>(&'b self) -> DisplayItemRef<'a, 'b> {
922 DisplayItemRef {
923 iter: self,
924 }
925 }
926
927 pub fn skip_current_stacking_context(&mut self) {
928 let mut depth = 0;
929 while let Some(item) = self.next() {
930 match *item.item() {
931 di::DisplayItem::PushStackingContext(..) => depth += 1,
932 di::DisplayItem::PopStackingContext if depth == 0 => return,
933 di::DisplayItem::PopStackingContext => depth -= 1,
934 _ => {}
935 }
936 }
937 }
938
939 pub fn current_stacking_context_empty(&mut self) -> bool {
940 match self.peek() {
941 Some(item) => *item.item() == di::DisplayItem::PopStackingContext,
942 None => true,
943 }
944 }
945
946 pub fn peek<'b>(&'b mut self) -> Option<DisplayItemRef<'a, 'b>> {
947 if self.peeking == Peek::NotPeeking {
948 self.peeking = Peek::StartPeeking;
949 self.next()
950 } else {
951 Some(self.as_ref())
952 }
953 }
954
955 pub fn debug_stats(&mut self) -> Vec<(&'static str, ItemStats)> {
958 let mut result = self.debug_stats.stats.drain().collect::<Vec<_>>();
959 result.sort_by_key(|stats| stats.0);
960 result
961 }
962
963 pub fn merge_debug_stats_from(&mut self, other: &mut Self) {
966 for (key, other_entry) in other.debug_stats.stats.iter() {
967 let entry = self.debug_stats.stats.entry(key).or_default();
968
969 entry.total_count += other_entry.total_count;
970 entry.num_bytes += other_entry.num_bytes;
971 }
972 }
973
974 #[cfg(feature = "display_list_stats")]
976 fn log_item_stats(&mut self) {
977 self.debug_stats.log_item(self.data, &self.cur_item);
978 }
979
980 #[cfg(not(feature = "display_list_stats"))]
981 fn log_item_stats(&mut self) { }
982}
983
984impl<'a, T> AuxIter<'a, T> {
985 pub fn new(item: T, mut data: &'a [u8]) -> Self {
986 let mut size = 0usize;
987 if !data.is_empty() {
988 data = peek_from_slice(data, &mut size);
989 };
990
991 AuxIter {
992 item,
993 data,
994 size,
995}
997 }
998}
999
1000impl<'a, T: Copy + peek_poke::Peek> Iterator for AuxIter<'a, T> {
1001 type Item = T;
1002
1003 fn next(&mut self) -> Option<Self::Item> {
1004 if self.size == 0 {
1005 None
1006 } else {
1007 self.size -= 1;
1008 self.data = peek_from_slice(self.data, &mut self.item);
1009 Some(self.item)
1010 }
1011 }
1012
1013 fn size_hint(&self) -> (usize, Option<usize>) {
1014 (self.size, Some(self.size))
1015 }
1016}
1017
1018impl<'a, T: Copy + peek_poke::Peek> ::std::iter::ExactSizeIterator for AuxIter<'a, T> {}
1019
1020#[derive(Clone, Debug)]
1021pub struct SaveState {
1022 dl_items_len: usize,
1023 dl_cache_len: usize,
1024 next_clip_index: usize,
1025 next_spatial_index: usize,
1026 next_clip_chain_id: u64,
1027}
1028
1029pub enum DisplayListSection {
1031 Data,
1033 CacheData,
1035 Chunk,
1038}
1039
1040pub struct DisplayListBuilder {
1041 payload: DisplayListPayload,
1042 pub pipeline_id: PipelineId,
1043
1044 pending_chunk: Vec<u8>,
1045 writing_to_chunk: bool,
1046
1047 next_clip_index: usize,
1048 next_spatial_index: usize,
1049 next_clip_chain_id: u64,
1050 builder_start_time: u64,
1051
1052 save_state: Option<SaveState>,
1053
1054 cache_size: usize,
1055 serialized_content_buffer: Option<String>,
1056 state: BuildState,
1057
1058 rf_mapper: ReferenceFrameMapper,
1060}
1061
1062#[repr(C)]
1063struct DisplayListCapacity {
1064 items_size: usize,
1065 cache_size: usize,
1066 spatial_tree_size: usize,
1067}
1068
1069impl DisplayListCapacity {
1070 fn empty() -> Self {
1071 DisplayListCapacity {
1072 items_size: 0,
1073 cache_size: 0,
1074 spatial_tree_size: 0,
1075 }
1076 }
1077}
1078
1079impl DisplayListBuilder {
1080 pub fn new(pipeline_id: PipelineId) -> Self {
1081 DisplayListBuilder {
1082 payload: DisplayListPayload::new(DisplayListCapacity::empty()),
1083 pipeline_id,
1084
1085 pending_chunk: Vec::new(),
1086 writing_to_chunk: false,
1087
1088 next_clip_index: FIRST_CLIP_NODE_INDEX,
1089 next_spatial_index: FIRST_SPATIAL_NODE_INDEX,
1090 next_clip_chain_id: 0,
1091 builder_start_time: 0,
1092 save_state: None,
1093 cache_size: 0,
1094 serialized_content_buffer: None,
1095 state: BuildState::Idle,
1096
1097 rf_mapper: ReferenceFrameMapper::new(),
1098 }
1099 }
1100
1101 fn reset(&mut self) {
1102 self.payload.clear();
1103 self.pending_chunk.clear();
1104 self.writing_to_chunk = false;
1105
1106 self.next_clip_index = FIRST_CLIP_NODE_INDEX;
1107 self.next_spatial_index = FIRST_SPATIAL_NODE_INDEX;
1108 self.next_clip_chain_id = 0;
1109
1110 self.save_state = None;
1111 self.cache_size = 0;
1112 self.serialized_content_buffer = None;
1113
1114 self.rf_mapper = ReferenceFrameMapper::new();
1115 }
1116
1117 pub fn save(&mut self) {
1125 assert!(self.save_state.is_none(), "DisplayListBuilder doesn't support nested saves");
1126
1127 self.save_state = Some(SaveState {
1128 dl_items_len: self.payload.items_data.len(),
1129 dl_cache_len: self.payload.cache_data.len(),
1130 next_clip_index: self.next_clip_index,
1131 next_spatial_index: self.next_spatial_index,
1132 next_clip_chain_id: self.next_clip_chain_id,
1133 });
1134 }
1135
1136 pub fn restore(&mut self) {
1138 let state = self.save_state.take().expect("No save to restore DisplayListBuilder from");
1139
1140 self.payload.items_data.truncate(state.dl_items_len);
1141 self.payload.cache_data.truncate(state.dl_cache_len);
1142 self.next_clip_index = state.next_clip_index;
1143 self.next_spatial_index = state.next_spatial_index;
1144 self.next_clip_chain_id = state.next_clip_chain_id;
1145 }
1146
1147 pub fn clear_save(&mut self) {
1149 self.save_state.take().expect("No save to clear in DisplayListBuilder");
1150 }
1151
1152 pub fn emit_display_list<W>(
1164 &mut self,
1165 indent: usize,
1166 range: Range<Option<usize>>,
1167 mut sink: W,
1168 ) -> usize
1169 where
1170 W: Write
1171 {
1172 let mut temp = BuiltDisplayList::default();
1173 ensure_red_zone::<di::DisplayItem>(&mut self.payload.items_data);
1174 ensure_red_zone::<di::DisplayItem>(&mut self.payload.cache_data);
1175 mem::swap(&mut temp.payload, &mut self.payload);
1176
1177 let mut index: usize = 0;
1178 {
1179 let mut cache = DisplayItemCache::new();
1180 cache.update(&temp);
1181 let mut iter = temp.iter_with_cache(&cache);
1182 while let Some(item) = iter.next_raw() {
1183 if index >= range.start.unwrap_or(0) && range.end.map_or(true, |e| index < e) {
1184 writeln!(sink, "{}{:?}", " ".repeat(indent), item.item()).unwrap();
1185 }
1186 index += 1;
1187 }
1188 }
1189
1190 self.payload = temp.payload;
1191 strip_red_zone::<di::DisplayItem>(&mut self.payload.items_data);
1192 strip_red_zone::<di::DisplayItem>(&mut self.payload.cache_data);
1193 index
1194 }
1195
1196 pub fn dump_serialized_display_list(&mut self) {
1198 self.serialized_content_buffer = Some(String::new());
1199 }
1200
1201 fn add_to_display_list_dump<T: std::fmt::Debug>(&mut self, item: T) {
1202 if let Some(ref mut content) = self.serialized_content_buffer {
1203 use std::fmt::Write;
1204 writeln!(content, "{:?}", item).expect("DL dump write failed.");
1205 }
1206 }
1207
1208 fn default_section(&self) -> DisplayListSection {
1211 if self.writing_to_chunk {
1212 DisplayListSection::Chunk
1213 } else {
1214 DisplayListSection::Data
1215 }
1216 }
1217
1218 fn buffer_from_section(
1219 &mut self,
1220 section: DisplayListSection
1221 ) -> &mut Vec<u8> {
1222 match section {
1223 DisplayListSection::Data => &mut self.payload.items_data,
1224 DisplayListSection::CacheData => &mut self.payload.cache_data,
1225 DisplayListSection::Chunk => &mut self.pending_chunk,
1226 }
1227 }
1228
1229 #[inline]
1230 pub fn push_item_to_section(
1231 &mut self,
1232 item: &di::DisplayItem,
1233 section: DisplayListSection,
1234 ) {
1235 debug_assert_eq!(self.state, BuildState::Build);
1236 poke_into_vec(item, self.buffer_from_section(section));
1237 self.add_to_display_list_dump(item);
1238 }
1239
1240 #[inline]
1246 pub fn push_item(&mut self, item: &di::DisplayItem) {
1247 self.push_item_to_section(item, self.default_section());
1248 }
1249
1250 #[inline]
1251 pub fn push_spatial_tree_item(&mut self, item: &di::SpatialTreeItem) {
1252 debug_assert_eq!(self.state, BuildState::Build);
1253 poke_into_vec(item, &mut self.payload.spatial_tree);
1254 }
1255
1256 fn push_iter_impl<I>(data: &mut Vec<u8>, iter_source: I)
1257 where
1258 I: IntoIterator,
1259 I::IntoIter: ExactSizeIterator,
1260 I::Item: Poke,
1261 {
1262 let iter = iter_source.into_iter();
1263 let len = iter.len();
1264 let byte_size_offset = data.len();
1271
1272 poke_into_vec(&0usize, data);
1274 poke_into_vec(&len, data);
1275 let count = poke_extend_vec(iter, data);
1276 debug_assert_eq!(len, count, "iterator.len() returned two different values");
1277
1278 ensure_red_zone::<I::Item>(data);
1280
1281 let final_offset = data.len();
1283 debug_assert!(final_offset >= (byte_size_offset + mem::size_of::<usize>()),
1284 "space was never allocated for this array's byte_size");
1285 let byte_size = final_offset - byte_size_offset - mem::size_of::<usize>();
1286 poke_inplace_slice(&byte_size, &mut data[byte_size_offset..]);
1287 }
1288
1289 pub fn push_iter<I>(&mut self, iter: I)
1294 where
1295 I: IntoIterator,
1296 I::IntoIter: ExactSizeIterator,
1297 I::Item: Poke,
1298 {
1299 assert_eq!(self.state, BuildState::Build);
1300
1301 let buffer = self.buffer_from_section(self.default_section());
1302 Self::push_iter_impl(buffer, iter);
1303 }
1304
1305 fn remap_common_coordinates_and_bounds(
1307 &self,
1308 common: &di::CommonItemProperties,
1309 bounds: LayoutRect,
1310 ) -> (di::CommonItemProperties, LayoutRect) {
1311 let offset = self.rf_mapper.current_offset();
1312
1313 (
1314 di::CommonItemProperties {
1315 clip_rect: common.clip_rect.translate(offset),
1316 ..*common
1317 },
1318 bounds.translate(offset),
1319 )
1320 }
1321
1322 fn remap_bounds(
1324 &self,
1325 bounds: LayoutRect,
1326 ) -> LayoutRect {
1327 let offset = self.rf_mapper.current_offset();
1328
1329 bounds.translate(offset)
1330 }
1331
1332 pub fn push_rect(
1333 &mut self,
1334 common: &di::CommonItemProperties,
1335 bounds: LayoutRect,
1336 color: ColorF,
1337 ) {
1338 let (common, bounds) = self.remap_common_coordinates_and_bounds(common, bounds);
1339
1340 let item = di::DisplayItem::Rectangle(di::RectangleDisplayItem {
1341 common,
1342 color: PropertyBinding::Value(color),
1343 bounds,
1344 });
1345 self.push_item(&item);
1346 }
1347
1348 pub fn push_rect_with_animation(
1349 &mut self,
1350 common: &di::CommonItemProperties,
1351 bounds: LayoutRect,
1352 color: PropertyBinding<ColorF>,
1353 ) {
1354 let (common, bounds) = self.remap_common_coordinates_and_bounds(common, bounds);
1355
1356 let item = di::DisplayItem::Rectangle(di::RectangleDisplayItem {
1357 common,
1358 color,
1359 bounds,
1360 });
1361 self.push_item(&item);
1362 }
1363
1364 pub fn push_clear_rect(
1365 &mut self,
1366 common: &di::CommonItemProperties,
1367 bounds: LayoutRect,
1368 ) {
1369 let (common, bounds) = self.remap_common_coordinates_and_bounds(common, bounds);
1370
1371 let item = di::DisplayItem::ClearRectangle(di::ClearRectangleDisplayItem {
1372 common,
1373 bounds,
1374 });
1375 self.push_item(&item);
1376 }
1377
1378 pub fn push_hit_test(
1379 &mut self,
1380 rect: LayoutRect,
1381 clip_chain_id: di::ClipChainId,
1382 spatial_id: di::SpatialId,
1383 flags: di::PrimitiveFlags,
1384 tag: di::ItemTag,
1385 ) {
1386 let rect = self.remap_bounds(rect);
1387
1388 let item = di::DisplayItem::HitTest(di::HitTestDisplayItem {
1389 rect,
1390 clip_chain_id,
1391 spatial_id,
1392 flags,
1393 tag,
1394 });
1395 self.push_item(&item);
1396 }
1397
1398 pub fn push_line(
1399 &mut self,
1400 common: &di::CommonItemProperties,
1401 area: &LayoutRect,
1402 wavy_line_thickness: f32,
1403 orientation: di::LineOrientation,
1404 color: &ColorF,
1405 style: di::LineStyle,
1406 ) {
1407 let (common, area) = self.remap_common_coordinates_and_bounds(common, *area);
1408
1409 let item = di::DisplayItem::Line(di::LineDisplayItem {
1410 common,
1411 area,
1412 wavy_line_thickness,
1413 orientation,
1414 color: *color,
1415 style,
1416 });
1417
1418 self.push_item(&item);
1419 }
1420
1421 pub fn push_image(
1422 &mut self,
1423 common: &di::CommonItemProperties,
1424 bounds: LayoutRect,
1425 image_rendering: di::ImageRendering,
1426 alpha_type: di::AlphaType,
1427 key: ImageKey,
1428 color: ColorF,
1429 ) {
1430 let (common, bounds) = self.remap_common_coordinates_and_bounds(common, bounds);
1431
1432 let item = di::DisplayItem::Image(di::ImageDisplayItem {
1433 common,
1434 bounds,
1435 image_key: key,
1436 image_rendering,
1437 alpha_type,
1438 color,
1439 });
1440
1441 self.push_item(&item);
1442 }
1443
1444 pub fn push_repeating_image(
1445 &mut self,
1446 common: &di::CommonItemProperties,
1447 bounds: LayoutRect,
1448 stretch_size: LayoutSize,
1449 tile_spacing: LayoutSize,
1450 image_rendering: di::ImageRendering,
1451 alpha_type: di::AlphaType,
1452 key: ImageKey,
1453 color: ColorF,
1454 ) {
1455 let (common, bounds) = self.remap_common_coordinates_and_bounds(common, bounds);
1456
1457 let item = di::DisplayItem::RepeatingImage(di::RepeatingImageDisplayItem {
1458 common,
1459 bounds,
1460 image_key: key,
1461 stretch_size,
1462 tile_spacing,
1463 image_rendering,
1464 alpha_type,
1465 color,
1466 });
1467
1468 self.push_item(&item);
1469 }
1470
1471 pub fn push_yuv_image(
1473 &mut self,
1474 common: &di::CommonItemProperties,
1475 bounds: LayoutRect,
1476 yuv_data: di::YuvData,
1477 color_depth: ColorDepth,
1478 color_space: di::YuvColorSpace,
1479 color_range: di::ColorRange,
1480 image_rendering: di::ImageRendering,
1481 ) {
1482 let (common, bounds) = self.remap_common_coordinates_and_bounds(common, bounds);
1483
1484 let item = di::DisplayItem::YuvImage(di::YuvImageDisplayItem {
1485 common,
1486 bounds,
1487 yuv_data,
1488 color_depth,
1489 color_space,
1490 color_range,
1491 image_rendering,
1492 });
1493 self.push_item(&item);
1494 }
1495
1496 pub fn push_text(
1497 &mut self,
1498 common: &di::CommonItemProperties,
1499 bounds: LayoutRect,
1500 glyphs: &[GlyphInstance],
1501 font_key: FontInstanceKey,
1502 color: ColorF,
1503 glyph_options: Option<GlyphOptions>,
1504 ) {
1505 let (common, bounds) = self.remap_common_coordinates_and_bounds(common, bounds);
1506 let ref_frame_offset = self.rf_mapper.current_offset();
1507
1508 let item = di::DisplayItem::Text(di::TextDisplayItem {
1509 common,
1510 bounds,
1511 color,
1512 font_key,
1513 glyph_options,
1514 ref_frame_offset,
1515 });
1516
1517 for split_glyphs in glyphs.chunks(MAX_TEXT_RUN_LENGTH) {
1518 self.push_item(&item);
1519 self.push_iter(split_glyphs);
1520 }
1521 }
1522
1523 pub fn create_gradient(
1526 &mut self,
1527 start_point: LayoutPoint,
1528 end_point: LayoutPoint,
1529 stops: Vec<di::GradientStop>,
1530 extend_mode: di::ExtendMode,
1531 ) -> di::Gradient {
1532 let mut builder = GradientBuilder::with_stops(stops);
1533 let gradient = builder.gradient(start_point, end_point, extend_mode);
1534 self.push_stops(builder.stops());
1535 gradient
1536 }
1537
1538 pub fn create_radial_gradient(
1541 &mut self,
1542 center: LayoutPoint,
1543 radius: LayoutSize,
1544 stops: Vec<di::GradientStop>,
1545 extend_mode: di::ExtendMode,
1546 ) -> di::RadialGradient {
1547 let mut builder = GradientBuilder::with_stops(stops);
1548 let gradient = builder.radial_gradient(center, radius, extend_mode);
1549 self.push_stops(builder.stops());
1550 gradient
1551 }
1552
1553 pub fn create_conic_gradient(
1556 &mut self,
1557 center: LayoutPoint,
1558 angle: f32,
1559 stops: Vec<di::GradientStop>,
1560 extend_mode: di::ExtendMode,
1561 ) -> di::ConicGradient {
1562 let mut builder = GradientBuilder::with_stops(stops);
1563 let gradient = builder.conic_gradient(center, angle, extend_mode);
1564 self.push_stops(builder.stops());
1565 gradient
1566 }
1567
1568 pub fn push_border(
1569 &mut self,
1570 common: &di::CommonItemProperties,
1571 bounds: LayoutRect,
1572 widths: LayoutSideOffsets,
1573 details: di::BorderDetails,
1574 ) {
1575 let (common, bounds) = self.remap_common_coordinates_and_bounds(common, bounds);
1576
1577 let item = di::DisplayItem::Border(di::BorderDisplayItem {
1578 common,
1579 bounds,
1580 details,
1581 widths,
1582 });
1583
1584 self.push_item(&item);
1585 }
1586
1587 pub fn push_box_shadow(
1588 &mut self,
1589 common: &di::CommonItemProperties,
1590 box_bounds: LayoutRect,
1591 offset: LayoutVector2D,
1592 color: ColorF,
1593 blur_radius: f32,
1594 spread_radius: f32,
1595 border_radius: di::BorderRadius,
1596 clip_mode: di::BoxShadowClipMode,
1597 ) {
1598 let (common, box_bounds) = self.remap_common_coordinates_and_bounds(common, box_bounds);
1599
1600 let item = di::DisplayItem::BoxShadow(di::BoxShadowDisplayItem {
1601 common,
1602 box_bounds,
1603 offset,
1604 color,
1605 blur_radius,
1606 spread_radius,
1607 border_radius,
1608 clip_mode,
1609 });
1610
1611 self.push_item(&item);
1612 }
1613
1614 pub fn push_gradient(
1629 &mut self,
1630 common: &di::CommonItemProperties,
1631 bounds: LayoutRect,
1632 gradient: di::Gradient,
1633 tile_size: LayoutSize,
1634 tile_spacing: LayoutSize,
1635 ) {
1636 let (common, bounds) = self.remap_common_coordinates_and_bounds(common, bounds);
1637
1638 let item = di::DisplayItem::Gradient(di::GradientDisplayItem {
1639 common,
1640 bounds,
1641 gradient,
1642 tile_size,
1643 tile_spacing,
1644 });
1645
1646 self.push_item(&item);
1647 }
1648
1649 pub fn push_radial_gradient(
1653 &mut self,
1654 common: &di::CommonItemProperties,
1655 bounds: LayoutRect,
1656 gradient: di::RadialGradient,
1657 tile_size: LayoutSize,
1658 tile_spacing: LayoutSize,
1659 ) {
1660 let (common, bounds) = self.remap_common_coordinates_and_bounds(common, bounds);
1661
1662 let item = di::DisplayItem::RadialGradient(di::RadialGradientDisplayItem {
1663 common,
1664 bounds,
1665 gradient,
1666 tile_size,
1667 tile_spacing,
1668 });
1669
1670 self.push_item(&item);
1671 }
1672
1673 pub fn push_conic_gradient(
1677 &mut self,
1678 common: &di::CommonItemProperties,
1679 bounds: LayoutRect,
1680 gradient: di::ConicGradient,
1681 tile_size: LayoutSize,
1682 tile_spacing: LayoutSize,
1683 ) {
1684 let (common, bounds) = self.remap_common_coordinates_and_bounds(common, bounds);
1685
1686 let item = di::DisplayItem::ConicGradient(di::ConicGradientDisplayItem {
1687 common,
1688 bounds,
1689 gradient,
1690 tile_size,
1691 tile_spacing,
1692 });
1693
1694 self.push_item(&item);
1695 }
1696
1697 pub fn push_reference_frame(
1698 &mut self,
1699 origin: LayoutPoint,
1700 parent_spatial_id: di::SpatialId,
1701 transform_style: di::TransformStyle,
1702 transform: PropertyBinding<LayoutTransform>,
1703 kind: di::ReferenceFrameKind,
1704 key: di::SpatialTreeItemKey,
1705 ) -> di::SpatialId {
1706 let id = self.generate_spatial_index();
1707
1708 let current_offset = self.rf_mapper.current_offset();
1709 let origin = origin + current_offset;
1710
1711 let descriptor = di::SpatialTreeItem::ReferenceFrame(di::ReferenceFrameDescriptor {
1712 parent_spatial_id,
1713 origin,
1714 reference_frame: di::ReferenceFrame {
1715 transform_style,
1716 transform: di::ReferenceTransformBinding::Static {
1717 binding: transform,
1718 },
1719 kind,
1720 id,
1721 key,
1722 },
1723 });
1724 self.push_spatial_tree_item(&descriptor);
1725
1726 self.rf_mapper.push_scope();
1727
1728 let item = di::DisplayItem::PushReferenceFrame(di::ReferenceFrameDisplayListItem {
1729 });
1730 self.push_item(&item);
1731
1732 id
1733 }
1734
1735 pub fn push_computed_frame(
1736 &mut self,
1737 origin: LayoutPoint,
1738 parent_spatial_id: di::SpatialId,
1739 scale_from: Option<LayoutSize>,
1740 vertical_flip: bool,
1741 rotation: di::Rotation,
1742 key: di::SpatialTreeItemKey,
1743 ) -> di::SpatialId {
1744 let id = self.generate_spatial_index();
1745
1746 let current_offset = self.rf_mapper.current_offset();
1747 let origin = origin + current_offset;
1748
1749 let descriptor = di::SpatialTreeItem::ReferenceFrame(di::ReferenceFrameDescriptor {
1750 parent_spatial_id,
1751 origin,
1752 reference_frame: di::ReferenceFrame {
1753 transform_style: di::TransformStyle::Flat,
1754 transform: di::ReferenceTransformBinding::Computed {
1755 scale_from,
1756 vertical_flip,
1757 rotation,
1758 },
1759 kind: di::ReferenceFrameKind::Transform {
1760 is_2d_scale_translation: false,
1761 should_snap: false,
1762 paired_with_perspective: false,
1763 },
1764 id,
1765 key,
1766 },
1767 });
1768 self.push_spatial_tree_item(&descriptor);
1769
1770 self.rf_mapper.push_scope();
1771
1772 let item = di::DisplayItem::PushReferenceFrame(di::ReferenceFrameDisplayListItem {
1773 });
1774 self.push_item(&item);
1775
1776 id
1777 }
1778
1779 pub fn pop_reference_frame(&mut self) {
1780 self.rf_mapper.pop_scope();
1781 self.push_item(&di::DisplayItem::PopReferenceFrame);
1782 }
1783
1784 pub fn push_stacking_context(
1785 &mut self,
1786 origin: LayoutPoint,
1787 spatial_id: di::SpatialId,
1788 prim_flags: di::PrimitiveFlags,
1789 clip_chain_id: Option<di::ClipChainId>,
1790 transform_style: di::TransformStyle,
1791 mix_blend_mode: di::MixBlendMode,
1792 filters: &[di::FilterOp],
1793 filter_datas: &[di::FilterData],
1794 filter_primitives: &[di::FilterPrimitive],
1795 raster_space: di::RasterSpace,
1796 flags: di::StackingContextFlags,
1797 snapshot: Option<di::SnapshotInfo>
1798 ) {
1799 let ref_frame_offset = self.rf_mapper.current_offset();
1800 self.push_filters(filters, filter_datas, filter_primitives);
1801
1802 let item = di::DisplayItem::PushStackingContext(di::PushStackingContextDisplayItem {
1803 origin,
1804 spatial_id,
1805 snapshot,
1806 prim_flags,
1807 ref_frame_offset,
1808 stacking_context: di::StackingContext {
1809 transform_style,
1810 mix_blend_mode,
1811 clip_chain_id,
1812 raster_space,
1813 flags,
1814 },
1815 });
1816
1817 self.rf_mapper.push_offset(origin.to_vector());
1818 self.push_item(&item);
1819 }
1820
1821 pub fn push_simple_stacking_context(
1823 &mut self,
1824 origin: LayoutPoint,
1825 spatial_id: di::SpatialId,
1826 prim_flags: di::PrimitiveFlags,
1827 ) {
1828 self.push_simple_stacking_context_with_filters(
1829 origin,
1830 spatial_id,
1831 prim_flags,
1832 &[],
1833 &[],
1834 &[],
1835 );
1836 }
1837
1838 pub fn push_simple_stacking_context_with_filters(
1840 &mut self,
1841 origin: LayoutPoint,
1842 spatial_id: di::SpatialId,
1843 prim_flags: di::PrimitiveFlags,
1844 filters: &[di::FilterOp],
1845 filter_datas: &[di::FilterData],
1846 filter_primitives: &[di::FilterPrimitive],
1847 ) {
1848 self.push_stacking_context(
1849 origin,
1850 spatial_id,
1851 prim_flags,
1852 None,
1853 di::TransformStyle::Flat,
1854 di::MixBlendMode::Normal,
1855 filters,
1856 filter_datas,
1857 filter_primitives,
1858 di::RasterSpace::Screen,
1859 di::StackingContextFlags::empty(),
1860 None,
1861 );
1862 }
1863
1864 pub fn pop_stacking_context(&mut self) {
1865 self.rf_mapper.pop_offset();
1866 self.push_item(&di::DisplayItem::PopStackingContext);
1867 }
1868
1869 pub fn push_stops(&mut self, stops: &[di::GradientStop]) {
1870 if stops.is_empty() {
1871 return;
1872 }
1873 self.push_item(&di::DisplayItem::SetGradientStops);
1874 self.push_iter(stops);
1875 }
1876
1877 pub fn push_backdrop_filter(
1878 &mut self,
1879 common: &di::CommonItemProperties,
1880 filters: &[di::FilterOp],
1881 filter_datas: &[di::FilterData],
1882 filter_primitives: &[di::FilterPrimitive],
1883 ) {
1884 let common = di::CommonItemProperties {
1885 clip_rect: self.remap_bounds(common.clip_rect),
1886 ..*common
1887 };
1888
1889 self.push_filters(filters, filter_datas, filter_primitives);
1890
1891 let item = di::DisplayItem::BackdropFilter(di::BackdropFilterDisplayItem {
1892 common,
1893 });
1894 self.push_item(&item);
1895 }
1896
1897 pub fn push_filters(
1898 &mut self,
1899 filters: &[di::FilterOp],
1900 filter_datas: &[di::FilterData],
1901 filter_primitives: &[di::FilterPrimitive],
1902 ) {
1903 if !filters.is_empty() {
1904 self.push_item(&di::DisplayItem::SetFilterOps);
1905 self.push_iter(filters);
1906 }
1907
1908 for filter_data in filter_datas {
1909 let func_types = [
1910 filter_data.func_r_type, filter_data.func_g_type,
1911 filter_data.func_b_type, filter_data.func_a_type];
1912 self.push_item(&di::DisplayItem::SetFilterData);
1913 self.push_iter(func_types);
1914 self.push_iter(&filter_data.r_values);
1915 self.push_iter(&filter_data.g_values);
1916 self.push_iter(&filter_data.b_values);
1917 self.push_iter(&filter_data.a_values);
1918 }
1919
1920 if !filter_primitives.is_empty() {
1921 self.push_item(&di::DisplayItem::SetFilterPrimitives);
1922 self.push_iter(filter_primitives);
1923 }
1924 }
1925
1926 pub fn push_debug(&mut self, val: u32) {
1927 self.push_item(&di::DisplayItem::DebugMarker(val));
1928 }
1929
1930 fn generate_clip_index(&mut self) -> di::ClipId {
1931 self.next_clip_index += 1;
1932 di::ClipId(self.next_clip_index - 1, self.pipeline_id)
1933 }
1934
1935 fn generate_spatial_index(&mut self) -> di::SpatialId {
1936 self.next_spatial_index += 1;
1937 di::SpatialId::new(self.next_spatial_index - 1, self.pipeline_id)
1938 }
1939
1940 fn generate_clip_chain_id(&mut self) -> di::ClipChainId {
1941 self.next_clip_chain_id += 1;
1942 di::ClipChainId(self.next_clip_chain_id - 1, self.pipeline_id)
1943 }
1944
1945 pub fn define_scroll_frame(
1946 &mut self,
1947 parent_space: di::SpatialId,
1948 external_id: di::ExternalScrollId,
1949 content_rect: LayoutRect,
1950 frame_rect: LayoutRect,
1951 external_scroll_offset: LayoutVector2D,
1952 scroll_offset_generation: APZScrollGeneration,
1953 has_scroll_linked_effect: HasScrollLinkedEffect,
1954 key: di::SpatialTreeItemKey,
1955 ) -> di::SpatialId {
1956 let scroll_frame_id = self.generate_spatial_index();
1957 let current_offset = self.rf_mapper.current_offset();
1958
1959 let descriptor = di::SpatialTreeItem::ScrollFrame(di::ScrollFrameDescriptor {
1960 content_rect,
1961 frame_rect: frame_rect.translate(current_offset),
1962 parent_space,
1963 scroll_frame_id,
1964 external_id,
1965 external_scroll_offset,
1966 scroll_offset_generation,
1967 has_scroll_linked_effect,
1968 key,
1969 });
1970
1971 self.push_spatial_tree_item(&descriptor);
1972
1973 scroll_frame_id
1974 }
1975
1976 pub fn define_clip_chain<I>(
1977 &mut self,
1978 parent: Option<di::ClipChainId>,
1979 clips: I,
1980 ) -> di::ClipChainId
1981 where
1982 I: IntoIterator<Item = di::ClipId>,
1983 I::IntoIter: ExactSizeIterator + Clone,
1984 {
1985 let id = self.generate_clip_chain_id();
1986 self.push_item(&di::DisplayItem::ClipChain(di::ClipChainItem { id, parent }));
1987 self.push_iter(clips);
1988 id
1989 }
1990
1991 pub fn define_clip_image_mask(
1992 &mut self,
1993 spatial_id: di::SpatialId,
1994 image_mask: di::ImageMask,
1995 points: &[LayoutPoint],
1996 fill_rule: di::FillRule,
1997 ) -> di::ClipId {
1998 let id = self.generate_clip_index();
1999
2000 let current_offset = self.rf_mapper.current_offset();
2001
2002 let image_mask = di::ImageMask {
2003 rect: image_mask.rect.translate(current_offset),
2004 ..image_mask
2005 };
2006
2007 let item = di::DisplayItem::ImageMaskClip(di::ImageMaskClipDisplayItem {
2008 id,
2009 spatial_id,
2010 image_mask,
2011 fill_rule,
2012 });
2013
2014 if points.len() >= 3 {
2019 self.push_item(&di::DisplayItem::SetPoints);
2020 self.push_iter(points);
2021 }
2022 self.push_item(&item);
2023 id
2024 }
2025
2026 pub fn define_clip_rect(
2027 &mut self,
2028 spatial_id: di::SpatialId,
2029 clip_rect: LayoutRect,
2030 ) -> di::ClipId {
2031 let id = self.generate_clip_index();
2032
2033 let current_offset = self.rf_mapper.current_offset();
2034 let clip_rect = clip_rect.translate(current_offset);
2035
2036 let item = di::DisplayItem::RectClip(di::RectClipDisplayItem {
2037 id,
2038 spatial_id,
2039 clip_rect,
2040 });
2041
2042 self.push_item(&item);
2043 id
2044 }
2045
2046 pub fn define_clip_rounded_rect(
2047 &mut self,
2048 spatial_id: di::SpatialId,
2049 clip: di::ComplexClipRegion,
2050 ) -> di::ClipId {
2051 let id = self.generate_clip_index();
2052
2053 let current_offset = self.rf_mapper.current_offset();
2054
2055 let clip = di::ComplexClipRegion {
2056 rect: clip.rect.translate(current_offset),
2057 ..clip
2058 };
2059
2060 let item = di::DisplayItem::RoundedRectClip(di::RoundedRectClipDisplayItem {
2061 id,
2062 spatial_id,
2063 clip,
2064 });
2065
2066 self.push_item(&item);
2067 id
2068 }
2069
2070 pub fn define_sticky_frame(
2071 &mut self,
2072 parent_spatial_id: di::SpatialId,
2073 frame_rect: LayoutRect,
2074 margins: SideOffsets2D<Option<f32>, LayoutPixel>,
2075 vertical_offset_bounds: di::StickyOffsetBounds,
2076 horizontal_offset_bounds: di::StickyOffsetBounds,
2077 previously_applied_offset: LayoutVector2D,
2078 key: di::SpatialTreeItemKey,
2079 transform: Option<PropertyBinding<LayoutTransform>>
2082 ) -> di::SpatialId {
2083 let id = self.generate_spatial_index();
2084 let current_offset = self.rf_mapper.current_offset();
2085
2086 let descriptor = di::SpatialTreeItem::StickyFrame(di::StickyFrameDescriptor {
2087 parent_spatial_id,
2088 id,
2089 bounds: frame_rect.translate(current_offset),
2090 margins,
2091 vertical_offset_bounds,
2092 horizontal_offset_bounds,
2093 previously_applied_offset,
2094 key,
2095 transform,
2096 });
2097
2098 self.push_spatial_tree_item(&descriptor);
2099 id
2100 }
2101
2102 pub fn push_iframe(
2103 &mut self,
2104 bounds: LayoutRect,
2105 clip_rect: LayoutRect,
2106 space_and_clip: &di::SpaceAndClipInfo,
2107 pipeline_id: PipelineId,
2108 ignore_missing_pipeline: bool
2109 ) {
2110 let current_offset = self.rf_mapper.current_offset();
2111 let bounds = bounds.translate(current_offset);
2112 let clip_rect = clip_rect.translate(current_offset);
2113
2114 let item = di::DisplayItem::Iframe(di::IframeDisplayItem {
2115 bounds,
2116 clip_rect,
2117 space_and_clip: *space_and_clip,
2118 pipeline_id,
2119 ignore_missing_pipeline,
2120 });
2121 self.push_item(&item);
2122 }
2123
2124 pub fn push_shadow(
2125 &mut self,
2126 space_and_clip: &di::SpaceAndClipInfo,
2127 shadow: di::Shadow,
2128 should_inflate: bool,
2129 ) {
2130 let item = di::DisplayItem::PushShadow(di::PushShadowDisplayItem {
2131 space_and_clip: *space_and_clip,
2132 shadow,
2133 should_inflate,
2134 });
2135 self.push_item(&item);
2136 }
2137
2138 pub fn pop_all_shadows(&mut self) {
2139 self.push_item(&di::DisplayItem::PopAllShadows);
2140 }
2141
2142 pub fn start_item_group(&mut self) {
2143 debug_assert!(!self.writing_to_chunk);
2144 debug_assert!(self.pending_chunk.is_empty());
2145
2146 self.writing_to_chunk = true;
2147 }
2148
2149 fn flush_pending_item_group(&mut self, key: di::ItemKey) {
2150 self.push_retained_items(key);
2152
2153 self.payload.cache_data.append(&mut self.pending_chunk);
2155
2156 self.push_reuse_items(key);
2158 }
2159
2160 pub fn finish_item_group(&mut self, key: di::ItemKey) -> bool {
2161 debug_assert!(self.writing_to_chunk);
2162 self.writing_to_chunk = false;
2163
2164 if self.pending_chunk.is_empty() {
2165 return false;
2166 }
2167
2168 self.flush_pending_item_group(key);
2169 true
2170 }
2171
2172 pub fn cancel_item_group(&mut self, discard: bool) {
2173 debug_assert!(self.writing_to_chunk);
2174 self.writing_to_chunk = false;
2175
2176 if discard {
2177 self.pending_chunk.clear();
2178 } else {
2179 self.payload.items_data.append(&mut self.pending_chunk);
2181 }
2182 }
2183
2184 pub fn push_reuse_items(&mut self, key: di::ItemKey) {
2185 self.push_item_to_section(
2186 &di::DisplayItem::ReuseItems(key),
2187 DisplayListSection::Data
2188 );
2189 }
2190
2191 fn push_retained_items(&mut self, key: di::ItemKey) {
2192 self.push_item_to_section(
2193 &di::DisplayItem::RetainedItems(key),
2194 DisplayListSection::CacheData
2195 );
2196 }
2197
2198 pub fn set_cache_size(&mut self, cache_size: usize) {
2199 self.cache_size = cache_size;
2200 }
2201
2202 pub fn begin(&mut self) {
2203 assert_eq!(self.state, BuildState::Idle);
2204 self.state = BuildState::Build;
2205 self.builder_start_time = precise_time_ns();
2206 self.reset();
2207 }
2208
2209 pub fn end(&mut self) -> (PipelineId, BuiltDisplayList) {
2210 assert_eq!(self.state, BuildState::Build);
2211 assert!(self.save_state.is_none(), "Finalized DisplayListBuilder with a pending save");
2212
2213 if let Some(content) = self.serialized_content_buffer.take() {
2214 println!("-- WebRender display list for {:?} --\n{}",
2215 self.pipeline_id, content);
2216 }
2217
2218 ensure_red_zone::<di::DisplayItem>(&mut self.payload.items_data);
2222 ensure_red_zone::<di::DisplayItem>(&mut self.payload.cache_data);
2223 ensure_red_zone::<di::SpatialTreeItem>(&mut self.payload.spatial_tree);
2224
2225 let next_capacity = DisplayListCapacity {
2231 cache_size: self.payload.cache_data.len(),
2232 items_size: self.payload.items_data.len(),
2233 spatial_tree_size: self.payload.spatial_tree.len(),
2234 };
2235 let payload = mem::replace(
2236 &mut self.payload,
2237 DisplayListPayload::new(next_capacity),
2238 );
2239 let end_time = precise_time_ns();
2240
2241 self.state = BuildState::Idle;
2242
2243 (
2244 self.pipeline_id,
2245 BuiltDisplayList {
2246 descriptor: BuiltDisplayListDescriptor {
2247 gecko_display_list_type: GeckoDisplayListType::None,
2248 builder_start_time: self.builder_start_time,
2249 builder_finish_time: end_time,
2250 send_start_time: end_time,
2251 total_clip_nodes: self.next_clip_index,
2252 total_spatial_nodes: self.next_spatial_index,
2253 cache_size: self.cache_size,
2254 },
2255 payload,
2256 },
2257 )
2258 }
2259}
2260
2261fn iter_spatial_tree<F>(spatial_tree: &[u8], mut f: F) where F: FnMut(&di::SpatialTreeItem) {
2262 let mut src = spatial_tree;
2263 let mut item = di::SpatialTreeItem::Invalid;
2264
2265 while src.len() > di::SpatialTreeItem::max_size() {
2266 src = peek_from_slice(src, &mut item);
2267 f(&item);
2268 }
2269}
2270
2271#[derive(Clone)]
2273struct ReferenceFrameState {
2274 offsets: Vec<LayoutVector2D>,
2276}
2277
2278#[derive(Clone)]
2281pub struct ReferenceFrameMapper {
2282 frames: Vec<ReferenceFrameState>,
2284}
2285
2286impl ReferenceFrameMapper {
2287 pub fn new() -> Self {
2288 ReferenceFrameMapper {
2289 frames: vec![
2290 ReferenceFrameState {
2291 offsets: vec![
2292 LayoutVector2D::zero(),
2293 ],
2294 }
2295 ],
2296 }
2297 }
2298
2299 pub fn push_scope(&mut self) {
2302 self.frames.push(ReferenceFrameState {
2303 offsets: vec![
2304 LayoutVector2D::zero(),
2305 ],
2306 });
2307 }
2308
2309 pub fn pop_scope(&mut self) {
2311 self.frames.pop().unwrap();
2312 }
2313
2314 pub fn push_offset(&mut self, offset: LayoutVector2D) {
2317 let frame = self.frames.last_mut().unwrap();
2318 let current_offset = *frame.offsets.last().unwrap();
2319 frame.offsets.push(current_offset + offset);
2320 }
2321
2322 pub fn pop_offset(&mut self) {
2324 let frame = self.frames.last_mut().unwrap();
2325 frame.offsets.pop().unwrap();
2326 }
2327
2328 pub fn current_offset(&self) -> LayoutVector2D {
2341 *self.frames.last().unwrap().offsets.last().unwrap()
2342 }
2343}