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