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