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 //! The high-level module responsible for managing the pipeline and preparing
6 //! commands to be issued by the `Renderer`.
7 //!
8 //! See the comment at the top of the `renderer` module for a description of
9 //! how these two pieces interact.
10 
11 use api::{DebugFlags, BlobImageHandler};
12 use api::{DocumentId, ExternalScrollId, HitTestResult};
13 use api::{IdNamespace, PipelineId, RenderNotifier, ScrollClamping};
14 use api::{NotificationRequest, Checkpoint, QualitySettings};
15 use api::{PrimitiveKeyKind};
16 use api::units::*;
17 use api::channel::{single_msg_channel, Sender, Receiver};
18 #[cfg(any(feature = "capture", feature = "replay"))]
19 use crate::render_api::CaptureBits;
20 #[cfg(feature = "replay")]
21 use crate::render_api::CapturedDocument;
22 use crate::render_api::{MemoryReport, TransactionMsg, ResourceUpdate, ApiMsg, FrameMsg, ClearCache, DebugCommand};
23 use crate::clip::{ClipIntern, PolygonIntern, ClipStoreScratchBuffer};
24 use crate::filterdata::FilterDataIntern;
25 #[cfg(any(feature = "capture", feature = "replay"))]
26 use crate::capture::CaptureConfig;
27 use crate::composite::{CompositorKind, CompositeDescriptor};
28 use crate::frame_builder::{FrameBuilder, FrameBuilderConfig, FrameScratchBuffer};
29 use crate::glyph_rasterizer::{FontInstance};
30 use crate::gpu_cache::GpuCache;
31 use crate::hit_test::{HitTest, HitTester, SharedHitTester};
32 use crate::intern::DataStore;
33 #[cfg(any(feature = "capture", feature = "replay"))]
34 use crate::internal_types::DebugOutput;
35 use crate::internal_types::{FastHashMap, RenderedDocument, ResultMsg};
36 use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
37 use crate::picture::{TileCacheLogger, PictureScratchBuffer, SliceId, TileCacheInstance, TileCacheParams};
38 use crate::prim_store::{PrimitiveScratchBuffer, PrimitiveInstance};
39 use crate::prim_store::{PrimitiveInstanceKind, PrimTemplateCommonData, PrimitiveStore};
40 use crate::prim_store::interned::*;
41 use crate::profiler::{self, TransactionProfile};
42 use crate::render_task_graph::RenderTaskGraphBuilder;
43 use crate::renderer::{AsyncPropertySampler, FullFrameStats, PipelineInfo};
44 use crate::resource_cache::ResourceCache;
45 #[cfg(feature = "replay")]
46 use crate::resource_cache::PlainCacheOwn;
47 #[cfg(feature = "replay")]
48 use crate::resource_cache::PlainResources;
49 #[cfg(feature = "replay")]
50 use crate::scene::Scene;
51 use crate::scene::{BuiltScene, SceneProperties};
52 use crate::scene_builder_thread::*;
53 #[cfg(feature = "serialize")]
54 use serde::{Serialize, Deserialize};
55 #[cfg(feature = "replay")]
56 use std::collections::hash_map::Entry::{Occupied, Vacant};
57 use std::sync::Arc;
58 use std::sync::atomic::{AtomicUsize, Ordering};
59 use std::time::{UNIX_EPOCH, SystemTime};
60 use std::{mem, u32};
61 #[cfg(feature = "capture")]
62 use std::path::PathBuf;
63 #[cfg(feature = "replay")]
64 use crate::frame_builder::Frame;
65 use time::precise_time_ns;
66 use crate::util::{Recycler, VecHelper, drain_filter};
67 
68 #[cfg_attr(feature = "capture", derive(Serialize))]
69 #[cfg_attr(feature = "replay", derive(Deserialize))]
70 #[derive(Copy, Clone)]
71 pub struct DocumentView {
72     scene: SceneView,
73 }
74 
75 /// Some rendering parameters applying at the scene level.
76 #[cfg_attr(feature = "capture", derive(Serialize))]
77 #[cfg_attr(feature = "replay", derive(Deserialize))]
78 #[derive(Copy, Clone)]
79 pub struct SceneView {
80     pub device_rect: DeviceIntRect,
81     pub quality_settings: QualitySettings,
82 }
83 
84 #[derive(Copy, Clone, Hash, MallocSizeOf, PartialEq, PartialOrd, Debug, Eq, Ord)]
85 #[cfg_attr(feature = "capture", derive(Serialize))]
86 #[cfg_attr(feature = "replay", derive(Deserialize))]
87 pub struct FrameId(usize);
88 
89 impl FrameId {
90     /// Returns a FrameId corresponding to the first frame.
91     ///
92     /// Note that we use 0 as the internal id here because the current code
93     /// increments the frame id at the beginning of the frame, rather than
94     /// at the end, and we want the first frame to be 1. It would probably
95     /// be sensible to move the advance() call to after frame-building, and
96     /// then make this method return FrameId(1).
first() -> Self97     pub fn first() -> Self {
98         FrameId(0)
99     }
100 
101     /// Returns the backing usize for this FrameId.
as_usize(&self) -> usize102     pub fn as_usize(&self) -> usize {
103         self.0
104     }
105 
106     /// Advances this FrameId to the next frame.
advance(&mut self)107     pub fn advance(&mut self) {
108         self.0 += 1;
109     }
110 
111     /// An invalid sentinel FrameId, which will always compare less than
112     /// any valid FrameId.
113     pub const INVALID: FrameId = FrameId(0);
114 }
115 
116 impl Default for FrameId {
default() -> Self117     fn default() -> Self {
118         FrameId::INVALID
119     }
120 }
121 
122 impl ::std::ops::Add<usize> for FrameId {
123     type Output = Self;
add(self, other: usize) -> FrameId124     fn add(self, other: usize) -> FrameId {
125         FrameId(self.0 + other)
126     }
127 }
128 
129 impl ::std::ops::Sub<usize> for FrameId {
130     type Output = Self;
sub(self, other: usize) -> FrameId131     fn sub(self, other: usize) -> FrameId {
132         assert!(self.0 >= other, "Underflow subtracting FrameIds");
133         FrameId(self.0 - other)
134     }
135 }
136 enum RenderBackendStatus {
137     Continue,
138     StopRenderBackend,
139     ShutDown(Option<Sender<()>>),
140 }
141 
142 /// Identifier to track a sequence of frames.
143 ///
144 /// This is effectively a `FrameId` with a ridealong timestamp corresponding
145 /// to when advance() was called, which allows for more nuanced cache eviction
146 /// decisions. As such, we use the `FrameId` for equality and comparison, since
147 /// we should never have two `FrameStamps` with the same id but different
148 /// timestamps.
149 #[derive(Copy, Clone, Debug, MallocSizeOf)]
150 #[cfg_attr(feature = "capture", derive(Serialize))]
151 #[cfg_attr(feature = "replay", derive(Deserialize))]
152 pub struct FrameStamp {
153     id: FrameId,
154     time: SystemTime,
155     document_id: DocumentId,
156 }
157 
158 impl Eq for FrameStamp {}
159 
160 impl PartialEq for FrameStamp {
eq(&self, other: &Self) -> bool161     fn eq(&self, other: &Self) -> bool {
162         // We should not be checking equality unless the documents are the same
163         debug_assert!(self.document_id == other.document_id);
164         self.id == other.id
165     }
166 }
167 
168 impl PartialOrd for FrameStamp {
partial_cmp(&self, other: &Self) -> Option<::std::cmp::Ordering>169     fn partial_cmp(&self, other: &Self) -> Option<::std::cmp::Ordering> {
170         self.id.partial_cmp(&other.id)
171     }
172 }
173 
174 impl FrameStamp {
175     /// Gets the FrameId in this stamp.
frame_id(&self) -> FrameId176     pub fn frame_id(&self) -> FrameId {
177         self.id
178     }
179 
180     /// Gets the time associated with this FrameStamp.
time(&self) -> SystemTime181     pub fn time(&self) -> SystemTime {
182         self.time
183     }
184 
185     /// Gets the DocumentId in this stamp.
document_id(&self) -> DocumentId186     pub fn document_id(&self) -> DocumentId {
187         self.document_id
188     }
189 
is_valid(&self) -> bool190     pub fn is_valid(&self) -> bool {
191         // If any fields are their default values, the whole struct should equal INVALID
192         debug_assert!((self.time != UNIX_EPOCH && self.id != FrameId(0) && self.document_id != DocumentId::INVALID) ||
193                       *self == Self::INVALID);
194         self.document_id != DocumentId::INVALID
195     }
196 
197     /// Returns a FrameStamp corresponding to the first frame.
first(document_id: DocumentId) -> Self198     pub fn first(document_id: DocumentId) -> Self {
199         FrameStamp {
200             id: FrameId::first(),
201             time: SystemTime::now(),
202             document_id,
203         }
204     }
205 
206     /// Advances to a new frame.
advance(&mut self)207     pub fn advance(&mut self) {
208         self.id.advance();
209         self.time = SystemTime::now();
210     }
211 
212     /// An invalid sentinel FrameStamp.
213     pub const INVALID: FrameStamp = FrameStamp {
214         id: FrameId(0),
215         time: UNIX_EPOCH,
216         document_id: DocumentId::INVALID,
217     };
218 }
219 
220 macro_rules! declare_data_stores {
221     ( $( $name:ident : $ty:ty, )+ ) => {
222         /// A collection of resources that are shared by clips, primitives
223         /// between display lists.
224         #[cfg_attr(feature = "capture", derive(Serialize))]
225         #[cfg_attr(feature = "replay", derive(Deserialize))]
226         #[derive(Default)]
227         pub struct DataStores {
228             $(
229                 pub $name: DataStore<$ty>,
230             )+
231         }
232 
233         impl DataStores {
234             /// Reports CPU heap usage.
235             fn report_memory(&self, ops: &mut MallocSizeOfOps, r: &mut MemoryReport) {
236                 $(
237                     r.interning.data_stores.$name += self.$name.size_of(ops);
238                 )+
239             }
240 
241             fn apply_updates(
242                 &mut self,
243                 updates: InternerUpdates,
244                 profile: &mut TransactionProfile,
245             ) {
246                 $(
247                     self.$name.apply_updates(
248                         updates.$name,
249                         profile,
250                     );
251                 )+
252             }
253         }
254     }
255 }
256 
257 crate::enumerate_interners!(declare_data_stores);
258 
259 impl DataStores {
260     /// Returns the local rect for a primitive. For most primitives, this is
261     /// stored in the template. For pictures, this is stored inside the picture
262     /// primitive instance itself, since this is determined during frame building.
get_local_prim_rect( &self, prim_instance: &PrimitiveInstance, prim_store: &PrimitiveStore, ) -> LayoutRect263     pub fn get_local_prim_rect(
264         &self,
265         prim_instance: &PrimitiveInstance,
266         prim_store: &PrimitiveStore,
267     ) -> LayoutRect {
268         match prim_instance.kind {
269             PrimitiveInstanceKind::Picture { pic_index, .. } => {
270                 let pic = &prim_store.pictures[pic_index.0];
271                 pic.precise_local_rect
272             }
273             _ => {
274                 self.as_common_data(prim_instance).prim_rect
275             }
276         }
277     }
278 
279     /// Returns true if this primitive might need repition.
280     // TODO(gw): This seems like the wrong place for this - maybe this flag should
281     //           not be in the common prim template data?
prim_may_need_repetition( &self, prim_instance: &PrimitiveInstance, ) -> bool282     pub fn prim_may_need_repetition(
283         &self,
284         prim_instance: &PrimitiveInstance,
285     ) -> bool {
286         match prim_instance.kind {
287             PrimitiveInstanceKind::Picture { .. } => {
288                 false
289             }
290             _ => {
291                 self.as_common_data(prim_instance).may_need_repetition
292             }
293         }
294     }
295 
as_common_data( &self, prim_inst: &PrimitiveInstance ) -> &PrimTemplateCommonData296     pub fn as_common_data(
297         &self,
298         prim_inst: &PrimitiveInstance
299     ) -> &PrimTemplateCommonData {
300         match prim_inst.kind {
301             PrimitiveInstanceKind::Rectangle { data_handle, .. } |
302             PrimitiveInstanceKind::Clear { data_handle, .. } => {
303                 let prim_data = &self.prim[data_handle];
304                 &prim_data.common
305             }
306             PrimitiveInstanceKind::Image { data_handle, .. } => {
307                 let prim_data = &self.image[data_handle];
308                 &prim_data.common
309             }
310             PrimitiveInstanceKind::ImageBorder { data_handle, .. } => {
311                 let prim_data = &self.image_border[data_handle];
312                 &prim_data.common
313             }
314             PrimitiveInstanceKind::LineDecoration { data_handle, .. } => {
315                 let prim_data = &self.line_decoration[data_handle];
316                 &prim_data.common
317             }
318             PrimitiveInstanceKind::LinearGradient { data_handle, .. }
319             | PrimitiveInstanceKind::CachedLinearGradient { data_handle, .. } => {
320                 let prim_data = &self.linear_grad[data_handle];
321                 &prim_data.common
322             }
323             PrimitiveInstanceKind::NormalBorder { data_handle, .. } => {
324                 let prim_data = &self.normal_border[data_handle];
325                 &prim_data.common
326             }
327             PrimitiveInstanceKind::Picture { .. } => {
328                 panic!("BUG: picture prims don't have common data!");
329             }
330             PrimitiveInstanceKind::RadialGradient { data_handle, .. } => {
331                 let prim_data = &self.radial_grad[data_handle];
332                 &prim_data.common
333             }
334             PrimitiveInstanceKind::ConicGradient { data_handle, .. } => {
335                 let prim_data = &self.conic_grad[data_handle];
336                 &prim_data.common
337             }
338             PrimitiveInstanceKind::TextRun { data_handle, .. }  => {
339                 let prim_data = &self.text_run[data_handle];
340                 &prim_data.common
341             }
342             PrimitiveInstanceKind::YuvImage { data_handle, .. } => {
343                 let prim_data = &self.yuv_image[data_handle];
344                 &prim_data.common
345             }
346             PrimitiveInstanceKind::Backdrop { data_handle, .. } => {
347                 let prim_data = &self.backdrop[data_handle];
348                 &prim_data.common
349             }
350         }
351     }
352 }
353 
354 #[derive(Default)]
355 pub struct ScratchBuffer {
356     pub primitive: PrimitiveScratchBuffer,
357     pub picture: PictureScratchBuffer,
358     pub frame: FrameScratchBuffer,
359     pub clip_store: ClipStoreScratchBuffer,
360 }
361 
362 impl ScratchBuffer {
begin_frame(&mut self)363     pub fn begin_frame(&mut self) {
364         self.primitive.begin_frame();
365         self.picture.begin_frame();
366         self.frame.begin_frame();
367     }
368 
end_frame(&mut self)369     pub fn end_frame(&mut self) {
370         self.primitive.end_frame();
371     }
372 
recycle(&mut self, recycler: &mut Recycler)373     pub fn recycle(&mut self, recycler: &mut Recycler) {
374         self.primitive.recycle(recycler);
375         self.picture.recycle(recycler);
376         self.frame.recycle(recycler);
377     }
378 
memory_pressure(&mut self)379     pub fn memory_pressure(&mut self) {
380         // TODO: causes browser chrome test crashes on windows.
381         //self.primitive = Default::default();
382         self.picture = Default::default();
383         self.frame = Default::default();
384         self.clip_store = Default::default();
385     }
386 }
387 
388 struct Document {
389     /// The id of this document
390     id: DocumentId,
391 
392     /// Temporary list of removed pipelines received from the scene builder
393     /// thread and forwarded to the renderer.
394     removed_pipelines: Vec<(PipelineId, DocumentId)>,
395 
396     view: DocumentView,
397 
398     /// The id and time of the current frame.
399     stamp: FrameStamp,
400 
401     /// The latest built scene, usable to build frames.
402     /// received from the scene builder thread.
403     scene: BuiltScene,
404 
405     /// The builder object that prodces frames, kept around to preserve some retained state.
406     frame_builder: FrameBuilder,
407 
408     /// Allows graphs of render tasks to be created, and then built into an immutable graph output.
409     rg_builder: RenderTaskGraphBuilder,
410 
411     /// A data structure to allow hit testing against rendered frames. This is updated
412     /// every time we produce a fully rendered frame.
413     hit_tester: Option<Arc<HitTester>>,
414     /// To avoid synchronous messaging we update a shared hit-tester that other threads
415     /// can query.
416     shared_hit_tester: Arc<SharedHitTester>,
417 
418     /// Properties that are resolved during frame building and can be changed at any time
419     /// without requiring the scene to be re-built.
420     dynamic_properties: SceneProperties,
421 
422     /// Track whether the last built frame is up to date or if it will need to be re-built
423     /// before rendering again.
424     frame_is_valid: bool,
425     hit_tester_is_valid: bool,
426     rendered_frame_is_valid: bool,
427     /// We track this information to be able to display debugging information from the
428     /// renderer.
429     has_built_scene: bool,
430 
431     data_stores: DataStores,
432 
433     /// Contains various vecs of data that is used only during frame building,
434     /// where we want to recycle the memory each new display list, to avoid constantly
435     /// re-allocating and moving memory around.
436     scratch: ScratchBuffer,
437 
438     #[cfg(feature = "replay")]
439     loaded_scene: Scene,
440 
441     /// Tracks the state of the picture cache tiles that were composited on the previous frame.
442     prev_composite_descriptor: CompositeDescriptor,
443 
444     /// Tracks if we need to invalidate dirty rects for this document, due to the picture
445     /// cache slice configuration having changed when a new scene is swapped in.
446     dirty_rects_are_valid: bool,
447 
448     profile: TransactionProfile,
449     frame_stats: Option<FullFrameStats>,
450 }
451 
452 impl Document {
new( id: DocumentId, size: DeviceIntSize, ) -> Self453     pub fn new(
454         id: DocumentId,
455         size: DeviceIntSize,
456     ) -> Self {
457         Document {
458             id,
459             removed_pipelines: Vec::new(),
460             view: DocumentView {
461                 scene: SceneView {
462                     device_rect: size.into(),
463                     quality_settings: QualitySettings::default(),
464                 },
465             },
466             stamp: FrameStamp::first(id),
467             scene: BuiltScene::empty(),
468             frame_builder: FrameBuilder::new(),
469             hit_tester: None,
470             shared_hit_tester: Arc::new(SharedHitTester::new()),
471             dynamic_properties: SceneProperties::new(),
472             frame_is_valid: false,
473             hit_tester_is_valid: false,
474             rendered_frame_is_valid: false,
475             has_built_scene: false,
476             data_stores: DataStores::default(),
477             scratch: ScratchBuffer::default(),
478             #[cfg(feature = "replay")]
479             loaded_scene: Scene::new(),
480             prev_composite_descriptor: CompositeDescriptor::empty(),
481             dirty_rects_are_valid: true,
482             profile: TransactionProfile::new(),
483             rg_builder: RenderTaskGraphBuilder::new(),
484             frame_stats: None,
485         }
486     }
487 
can_render(&self) -> bool488     fn can_render(&self) -> bool {
489         self.scene.has_root_pipeline
490     }
491 
has_pixels(&self) -> bool492     fn has_pixels(&self) -> bool {
493         !self.view.scene.device_rect.is_empty()
494     }
495 
process_frame_msg( &mut self, message: FrameMsg, ) -> DocumentOps496     fn process_frame_msg(
497         &mut self,
498         message: FrameMsg,
499     ) -> DocumentOps {
500         match message {
501             FrameMsg::UpdateEpoch(pipeline_id, epoch) => {
502                 self.scene.pipeline_epochs.insert(pipeline_id, epoch);
503             }
504             FrameMsg::HitTest(pipeline_id, point, tx) => {
505                 if !self.hit_tester_is_valid {
506                     self.rebuild_hit_tester();
507                 }
508 
509                 let result = match self.hit_tester {
510                     Some(ref hit_tester) => {
511                         hit_tester.hit_test(HitTest::new(pipeline_id, point))
512                     }
513                     None => HitTestResult { items: Vec::new() },
514                 };
515 
516                 tx.send(result).unwrap();
517             }
518             FrameMsg::RequestHitTester(tx) => {
519                 tx.send(self.shared_hit_tester.clone()).unwrap();
520             }
521             FrameMsg::ScrollNodeWithId(origin, id, clamp) => {
522                 profile_scope!("ScrollNodeWithScrollId");
523 
524                 if self.scroll_node(origin, id, clamp) {
525                     self.hit_tester_is_valid = false;
526                     self.frame_is_valid = false;
527                 }
528 
529                 return DocumentOps {
530                     scroll: true,
531                     ..DocumentOps::nop()
532                 };
533             }
534             FrameMsg::GetScrollNodeState(tx) => {
535                 profile_scope!("GetScrollNodeState");
536                 tx.send(self.scene.spatial_tree.get_scroll_node_state()).unwrap();
537             }
538             FrameMsg::UpdateDynamicProperties(property_bindings) => {
539                 self.dynamic_properties.set_properties(property_bindings);
540             }
541             FrameMsg::AppendDynamicTransformProperties(property_bindings) => {
542                 self.dynamic_properties.add_transforms(property_bindings);
543             }
544             FrameMsg::SetIsTransformAsyncZooming(is_zooming, animation_id) => {
545                 let node = self.scene.spatial_tree.spatial_nodes.iter_mut()
546                     .find(|node| node.is_transform_bound_to_property(animation_id));
547                 if let Some(node) = node {
548                     if node.is_async_zooming != is_zooming {
549                         node.is_async_zooming = is_zooming;
550                         self.frame_is_valid = false;
551                     }
552                 }
553             }
554         }
555 
556         DocumentOps::nop()
557     }
558 
build_frame( &mut self, resource_cache: &mut ResourceCache, gpu_cache: &mut GpuCache, debug_flags: DebugFlags, tile_cache_logger: &mut TileCacheLogger, tile_caches: &mut FastHashMap<SliceId, Box<TileCacheInstance>>, frame_stats: Option<FullFrameStats> ) -> RenderedDocument559     fn build_frame(
560         &mut self,
561         resource_cache: &mut ResourceCache,
562         gpu_cache: &mut GpuCache,
563         debug_flags: DebugFlags,
564         tile_cache_logger: &mut TileCacheLogger,
565         tile_caches: &mut FastHashMap<SliceId, Box<TileCacheInstance>>,
566         frame_stats: Option<FullFrameStats>
567     ) -> RenderedDocument {
568         let frame_build_start_time = precise_time_ns();
569 
570         // Advance to the next frame.
571         self.stamp.advance();
572 
573         assert!(self.stamp.frame_id() != FrameId::INVALID,
574                 "First frame increment must happen before build_frame()");
575 
576         let frame = {
577             let frame = self.frame_builder.build(
578                 &mut self.scene,
579                 resource_cache,
580                 gpu_cache,
581                 &mut self.rg_builder,
582                 self.stamp,
583                 self.view.scene.device_rect.min,
584                 &self.dynamic_properties,
585                 &mut self.data_stores,
586                 &mut self.scratch,
587                 debug_flags,
588                 tile_cache_logger,
589                 tile_caches,
590                 self.dirty_rects_are_valid,
591                 &mut self.profile,
592             );
593 
594             frame
595         };
596 
597         self.frame_is_valid = true;
598         self.dirty_rects_are_valid = true;
599 
600         let is_new_scene = self.has_built_scene;
601         self.has_built_scene = false;
602 
603         let frame_build_time_ms =
604             profiler::ns_to_ms(precise_time_ns() - frame_build_start_time);
605         self.profile.set(profiler::FRAME_BUILDING_TIME, frame_build_time_ms);
606 
607         let frame_stats = frame_stats.map(|mut stats| {
608             stats.frame_build_time += frame_build_time_ms;
609             stats
610         });
611 
612         RenderedDocument {
613             frame,
614             is_new_scene,
615             profile: self.profile.take_and_reset(),
616             frame_stats: frame_stats
617         }
618     }
619 
rebuild_hit_tester(&mut self)620     fn rebuild_hit_tester(&mut self) {
621         self.scene.spatial_tree.update_tree(&self.dynamic_properties);
622 
623         let hit_tester = Arc::new(self.scene.create_hit_tester());
624         self.hit_tester = Some(Arc::clone(&hit_tester));
625         self.shared_hit_tester.update(hit_tester);
626         self.hit_tester_is_valid = true;
627     }
628 
updated_pipeline_info(&mut self) -> PipelineInfo629     pub fn updated_pipeline_info(&mut self) -> PipelineInfo {
630         let removed_pipelines = self.removed_pipelines.take_and_preallocate();
631         PipelineInfo {
632             epochs: self.scene.pipeline_epochs.iter()
633                 .map(|(&pipeline_id, &epoch)| ((pipeline_id, self.id), epoch)).collect(),
634             removed_pipelines,
635         }
636     }
637 
638     /// Returns true if the node actually changed position or false otherwise.
scroll_node( &mut self, origin: LayoutPoint, id: ExternalScrollId, clamp: ScrollClamping ) -> bool639     pub fn scroll_node(
640         &mut self,
641         origin: LayoutPoint,
642         id: ExternalScrollId,
643         clamp: ScrollClamping
644     ) -> bool {
645         self.scene.spatial_tree.scroll_node(origin, id, clamp)
646     }
647 
648     /// Update the state of tile caches when a new scene is being swapped in to
649     /// the render backend. Retain / reuse existing caches if possible, and
650     /// destroy any now unused caches.
update_tile_caches_for_new_scene( &mut self, mut requested_tile_caches: FastHashMap<SliceId, TileCacheParams>, tile_caches: &mut FastHashMap<SliceId, Box<TileCacheInstance>>, resource_cache: &mut ResourceCache, )651     fn update_tile_caches_for_new_scene(
652         &mut self,
653         mut requested_tile_caches: FastHashMap<SliceId, TileCacheParams>,
654         tile_caches: &mut FastHashMap<SliceId, Box<TileCacheInstance>>,
655         resource_cache: &mut ResourceCache,
656     ) {
657         let mut new_tile_caches = FastHashMap::default();
658         new_tile_caches.reserve(requested_tile_caches.len());
659 
660         // Step through the tile caches that are needed for the new scene, and see
661         // if we have an existing cache that can be reused.
662         for (slice_id, params) in requested_tile_caches.drain() {
663             let tile_cache = match tile_caches.remove(&slice_id) {
664                 Some(mut existing_tile_cache) => {
665                     // Found an existing cache - update the cache params and reuse it
666                     existing_tile_cache.prepare_for_new_scene(
667                         params,
668                         resource_cache,
669                     );
670                     existing_tile_cache
671                 }
672                 None => {
673                     // No cache exists so create a new one
674                     Box::new(TileCacheInstance::new(params))
675                 }
676             };
677 
678             new_tile_caches.insert(slice_id, tile_cache);
679         }
680 
681         // Replace current tile cache map, and return what was left over,
682         // which are now unused.
683         let unused_tile_caches = mem::replace(
684             tile_caches,
685             new_tile_caches,
686         );
687 
688         if !unused_tile_caches.is_empty() {
689             // If the slice configuration changed, assume we can't rely on the
690             // current dirty rects for next composite
691             self.dirty_rects_are_valid = false;
692 
693             // Destroy any native surfaces allocated by these unused caches
694             for (_, tile_cache) in unused_tile_caches {
695                 tile_cache.destroy(resource_cache);
696             }
697         }
698     }
699 
new_async_scene_ready( &mut self, mut built_scene: BuiltScene, recycler: &mut Recycler, tile_caches: &mut FastHashMap<SliceId, Box<TileCacheInstance>>, resource_cache: &mut ResourceCache, )700     pub fn new_async_scene_ready(
701         &mut self,
702         mut built_scene: BuiltScene,
703         recycler: &mut Recycler,
704         tile_caches: &mut FastHashMap<SliceId, Box<TileCacheInstance>>,
705         resource_cache: &mut ResourceCache,
706     ) {
707         self.frame_is_valid = false;
708         self.hit_tester_is_valid = false;
709 
710         self.update_tile_caches_for_new_scene(
711             mem::replace(&mut built_scene.tile_cache_config.tile_caches, FastHashMap::default()),
712             tile_caches,
713             resource_cache,
714         );
715 
716         let old_scrolling_states = self.scene.spatial_tree.drain();
717         self.scene = built_scene;
718         self.scratch.recycle(recycler);
719         self.scene.spatial_tree.finalize_and_apply_pending_scroll_offsets(old_scrolling_states);
720     }
721 }
722 
723 struct DocumentOps {
724     scroll: bool,
725 }
726 
727 impl DocumentOps {
nop() -> Self728     fn nop() -> Self {
729         DocumentOps {
730             scroll: false,
731         }
732     }
733 }
734 
735 /// The unique id for WR resource identification.
736 /// The namespace_id should start from 1.
737 static NEXT_NAMESPACE_ID: AtomicUsize = AtomicUsize::new(1);
738 
739 #[cfg(any(feature = "capture", feature = "replay"))]
740 #[cfg_attr(feature = "capture", derive(Serialize))]
741 #[cfg_attr(feature = "replay", derive(Deserialize))]
742 struct PlainRenderBackend {
743     frame_config: FrameBuilderConfig,
744     documents: FastHashMap<DocumentId, DocumentView>,
745     resource_sequence_id: u32,
746 }
747 
748 /// The render backend is responsible for transforming high level display lists into
749 /// GPU-friendly work which is then submitted to the renderer in the form of a frame::Frame.
750 ///
751 /// The render backend operates on its own thread.
752 pub struct RenderBackend {
753     api_rx: Receiver<ApiMsg>,
754     result_tx: Sender<ResultMsg>,
755     scene_tx: Sender<SceneBuilderRequest>,
756 
757     gpu_cache: GpuCache,
758     resource_cache: ResourceCache,
759 
760     frame_config: FrameBuilderConfig,
761     default_compositor_kind: CompositorKind,
762     documents: FastHashMap<DocumentId, Document>,
763 
764     notifier: Box<dyn RenderNotifier>,
765     tile_cache_logger: TileCacheLogger,
766     sampler: Option<Box<dyn AsyncPropertySampler + Send>>,
767     size_of_ops: Option<MallocSizeOfOps>,
768     debug_flags: DebugFlags,
769     namespace_alloc_by_client: bool,
770 
771     // We keep one around to be able to call clear_namespace
772     // after the api object is deleted. For most purposes the
773     // api object's blob handler should be used instead.
774     blob_image_handler: Option<Box<dyn BlobImageHandler>>,
775 
776     recycler: Recycler,
777 
778     #[cfg(feature = "capture")]
779     /// If `Some`, do 'sequence capture' logging, recording updated documents,
780     /// frames, etc. This is set only through messages from the scene builder,
781     /// so all control of sequence capture goes through there.
782     capture_config: Option<CaptureConfig>,
783 
784     #[cfg(feature = "replay")]
785     loaded_resource_sequence_id: u32,
786 
787     /// A map of tile caches. These are stored in the backend as they are
788     /// persisted between both frame and scenes.
789     tile_caches: FastHashMap<SliceId, Box<TileCacheInstance>>,
790 }
791 
792 impl RenderBackend {
new( api_rx: Receiver<ApiMsg>, result_tx: Sender<ResultMsg>, scene_tx: Sender<SceneBuilderRequest>, resource_cache: ResourceCache, notifier: Box<dyn RenderNotifier>, blob_image_handler: Option<Box<dyn BlobImageHandler>>, frame_config: FrameBuilderConfig, sampler: Option<Box<dyn AsyncPropertySampler + Send>>, size_of_ops: Option<MallocSizeOfOps>, debug_flags: DebugFlags, namespace_alloc_by_client: bool, ) -> RenderBackend793     pub fn new(
794         api_rx: Receiver<ApiMsg>,
795         result_tx: Sender<ResultMsg>,
796         scene_tx: Sender<SceneBuilderRequest>,
797         resource_cache: ResourceCache,
798         notifier: Box<dyn RenderNotifier>,
799         blob_image_handler: Option<Box<dyn BlobImageHandler>>,
800         frame_config: FrameBuilderConfig,
801         sampler: Option<Box<dyn AsyncPropertySampler + Send>>,
802         size_of_ops: Option<MallocSizeOfOps>,
803         debug_flags: DebugFlags,
804         namespace_alloc_by_client: bool,
805     ) -> RenderBackend {
806         RenderBackend {
807             api_rx,
808             result_tx,
809             scene_tx,
810             resource_cache,
811             gpu_cache: GpuCache::new(),
812             frame_config,
813             default_compositor_kind : frame_config.compositor_kind,
814             documents: FastHashMap::default(),
815             notifier,
816             tile_cache_logger: TileCacheLogger::new(500usize),
817             sampler,
818             size_of_ops,
819             debug_flags,
820             namespace_alloc_by_client,
821             recycler: Recycler::new(),
822             blob_image_handler,
823             #[cfg(feature = "capture")]
824             capture_config: None,
825             #[cfg(feature = "replay")]
826             loaded_resource_sequence_id: 0,
827             tile_caches: FastHashMap::default(),
828         }
829     }
830 
next_namespace_id(&self) -> IdNamespace831     fn next_namespace_id(&self) -> IdNamespace {
832         IdNamespace(NEXT_NAMESPACE_ID.fetch_add(1, Ordering::Relaxed) as u32)
833     }
834 
run(&mut self)835     pub fn run(&mut self) {
836         let mut frame_counter: u32 = 0;
837         let mut status = RenderBackendStatus::Continue;
838 
839         if let Some(ref sampler) = self.sampler {
840             sampler.register();
841         }
842 
843         while let RenderBackendStatus::Continue = status {
844             status = match self.api_rx.recv() {
845                 Ok(msg) => {
846                     self.process_api_msg(msg, &mut frame_counter)
847                 }
848                 Err(..) => { RenderBackendStatus::ShutDown(None) }
849             };
850         }
851 
852         if let RenderBackendStatus::StopRenderBackend = status {
853             while let Ok(msg) = self.api_rx.recv() {
854                 match msg {
855                     ApiMsg::SceneBuilderResult(SceneBuilderResult::ExternalEvent(evt)) => {
856                         self.notifier.external_event(evt);
857                     }
858                     ApiMsg::SceneBuilderResult(SceneBuilderResult::FlushComplete(tx)) => {
859                         // If somebody's blocked waiting for a flush, how did they
860                         // trigger the RB thread to shut down? This shouldn't happen
861                         // but handle it gracefully anyway.
862                         debug_assert!(false);
863                         tx.send(()).ok();
864                     }
865                     ApiMsg::SceneBuilderResult(SceneBuilderResult::ShutDown(sender)) => {
866                         info!("Recycling stats: {:?}", self.recycler);
867                         status = RenderBackendStatus::ShutDown(sender);
868                         break;
869                    }
870                     _ => {},
871                 }
872             }
873         }
874 
875         // Ensure we read everything the scene builder is sending us from
876         // inflight messages, otherwise the scene builder might panic.
877         while let Ok(msg) = self.api_rx.try_recv() {
878             match msg {
879                 ApiMsg::SceneBuilderResult(SceneBuilderResult::FlushComplete(tx)) => {
880                     // If somebody's blocked waiting for a flush, how did they
881                     // trigger the RB thread to shut down? This shouldn't happen
882                     // but handle it gracefully anyway.
883                     debug_assert!(false);
884                     tx.send(()).ok();
885                 }
886                 _ => {},
887             }
888         }
889 
890         self.documents.clear();
891 
892         self.notifier.shut_down();
893 
894         if let Some(ref sampler) = self.sampler {
895             sampler.deregister();
896         }
897 
898 
899         if let RenderBackendStatus::ShutDown(Some(sender)) = status {
900             let _ = sender.send(());
901         }
902     }
903 
process_transaction( &mut self, mut txns: Vec<Box<BuiltTransaction>>, result_tx: Option<Sender<SceneSwapResult>>, frame_counter: &mut u32, ) -> bool904     fn process_transaction(
905         &mut self,
906         mut txns: Vec<Box<BuiltTransaction>>,
907         result_tx: Option<Sender<SceneSwapResult>>,
908         frame_counter: &mut u32,
909     ) -> bool {
910         self.prepare_for_frames();
911         self.maybe_force_nop_documents(
912             frame_counter,
913             |document_id| txns.iter().any(|txn| txn.document_id == document_id));
914 
915         let mut built_frame = false;
916         for mut txn in txns.drain(..) {
917            let has_built_scene = txn.built_scene.is_some();
918 
919             if let Some(doc) = self.documents.get_mut(&txn.document_id) {
920                 doc.removed_pipelines.append(&mut txn.removed_pipelines);
921                 doc.view.scene = txn.view;
922                 doc.profile.merge(&mut txn.profile);
923 
924                 doc.frame_stats = if let Some(stats) = &doc.frame_stats {
925                     Some(stats.merge(&txn.frame_stats))
926                 } else {
927                     Some(txn.frame_stats)
928                 };
929 
930                 if let Some(built_scene) = txn.built_scene.take() {
931                     doc.new_async_scene_ready(
932                         built_scene,
933                         &mut self.recycler,
934                         &mut self.tile_caches,
935                         &mut self.resource_cache,
936                     );
937                 }
938 
939                 // If there are any additions or removals of clip modes
940                 // during the scene build, apply them to the data store now.
941                 // This needs to happen before we build the hit tester.
942                 if let Some(updates) = txn.interner_updates.take() {
943                     #[cfg(feature = "capture")]
944                     {
945                         if self.debug_flags.contains(DebugFlags::TILE_CACHE_LOGGING_DBG) {
946                             self.tile_cache_logger.serialize_updates(&updates);
947                         }
948                     }
949                     doc.data_stores.apply_updates(updates, &mut doc.profile);
950                 }
951 
952                 // Build the hit tester while the APZ lock is held so that its content
953                 // is in sync with the gecko APZ tree.
954                 if !doc.hit_tester_is_valid {
955                     doc.rebuild_hit_tester();
956                 }
957 
958                 if let Some(ref tx) = result_tx {
959                     let (resume_tx, resume_rx) = single_msg_channel();
960                     tx.send(SceneSwapResult::Complete(resume_tx)).unwrap();
961                     // Block until the post-swap hook has completed on
962                     // the scene builder thread. We need to do this before
963                     // we can sample from the sampler hook which might happen
964                     // in the update_document call below.
965                     resume_rx.recv().ok();
966                 }
967 
968                 for pipeline_id in &txn.discard_frame_state_for_pipelines {
969                     doc.scene
970                         .spatial_tree
971                         .discard_frame_state_for_pipeline(*pipeline_id);
972                 }
973 
974                 self.resource_cache.add_rasterized_blob_images(
975                     txn.rasterized_blobs.take(),
976                     &mut doc.profile,
977                 );
978 
979             } else {
980                 // The document was removed while we were building it, skip it.
981                 // TODO: we might want to just ensure that removed documents are
982                 // always forwarded to the scene builder thread to avoid this case.
983                 if let Some(ref tx) = result_tx {
984                     tx.send(SceneSwapResult::Aborted).unwrap();
985                 }
986                 continue;
987             }
988 
989             built_frame |= self.update_document(
990                 txn.document_id,
991                 txn.resource_updates.take(),
992                 txn.frame_ops.take(),
993                 txn.notifications.take(),
994                 txn.render_frame,
995                 None,
996                 txn.invalidate_rendered_frame,
997                 frame_counter,
998                 has_built_scene,
999             );
1000         }
1001 
1002         built_frame
1003     }
1004 
process_api_msg( &mut self, msg: ApiMsg, frame_counter: &mut u32, ) -> RenderBackendStatus1005     fn process_api_msg(
1006         &mut self,
1007         msg: ApiMsg,
1008         frame_counter: &mut u32,
1009     ) -> RenderBackendStatus {
1010         match msg {
1011             ApiMsg::CloneApi(sender) => {
1012                 assert!(!self.namespace_alloc_by_client);
1013                 sender.send(self.next_namespace_id()).unwrap();
1014             }
1015             ApiMsg::CloneApiByClient(namespace_id) => {
1016                 assert!(self.namespace_alloc_by_client);
1017                 debug_assert!(!self.documents.iter().any(|(did, _doc)| did.namespace_id == namespace_id));
1018             }
1019             ApiMsg::AddDocument(document_id, initial_size) => {
1020                 let document = Document::new(
1021                     document_id,
1022                     initial_size,
1023                 );
1024                 let old = self.documents.insert(document_id, document);
1025                 debug_assert!(old.is_none());
1026             }
1027             ApiMsg::MemoryPressure => {
1028                 // This is drastic. It will basically flush everything out of the cache,
1029                 // and the next frame will have to rebuild all of its resources.
1030                 // We may want to look into something less extreme, but on the other hand this
1031                 // should only be used in situations where are running low enough on memory
1032                 // that we risk crashing if we don't do something about it.
1033                 // The advantage of clearing the cache completely is that it gets rid of any
1034                 // remaining fragmentation that could have persisted if we kept around the most
1035                 // recently used resources.
1036                 self.resource_cache.clear(ClearCache::all());
1037 
1038                 self.gpu_cache.clear();
1039 
1040                 for (_, doc) in &mut self.documents {
1041                     doc.scratch.memory_pressure();
1042                 }
1043 
1044                 let resource_updates = self.resource_cache.pending_updates();
1045                 let msg = ResultMsg::UpdateResources {
1046                     resource_updates,
1047                     memory_pressure: true,
1048                 };
1049                 self.result_tx.send(msg).unwrap();
1050                 self.notifier.wake_up(false);
1051             }
1052             ApiMsg::ReportMemory(tx) => {
1053                 self.report_memory(tx);
1054             }
1055             ApiMsg::DebugCommand(option) => {
1056                 let msg = match option {
1057                     DebugCommand::EnableDualSourceBlending(enable) => {
1058                         // Set in the config used for any future documents
1059                         // that are created.
1060                         self.frame_config
1061                             .dual_source_blending_is_enabled = enable;
1062                         self.update_frame_builder_config();
1063 
1064                         // We don't want to forward this message to the renderer.
1065                         return RenderBackendStatus::Continue;
1066                     }
1067                     DebugCommand::SetPictureTileSize(tile_size) => {
1068                         self.frame_config.tile_size_override = tile_size;
1069                         self.update_frame_builder_config();
1070 
1071                         return RenderBackendStatus::Continue;
1072                     }
1073                     #[cfg(feature = "capture")]
1074                     DebugCommand::SaveCapture(root, bits) => {
1075                         let output = self.save_capture(root, bits);
1076                         ResultMsg::DebugOutput(output)
1077                     },
1078                     #[cfg(feature = "capture")]
1079                     DebugCommand::StartCaptureSequence(root, bits) => {
1080                         self.start_capture_sequence(root, bits);
1081                         return RenderBackendStatus::Continue;
1082                     },
1083                     #[cfg(feature = "capture")]
1084                     DebugCommand::StopCaptureSequence => {
1085                         self.stop_capture_sequence();
1086                         return RenderBackendStatus::Continue;
1087                     },
1088                     #[cfg(feature = "replay")]
1089                     DebugCommand::LoadCapture(path, ids, tx) => {
1090                         NEXT_NAMESPACE_ID.fetch_add(1, Ordering::Relaxed);
1091                         *frame_counter += 1;
1092 
1093                         let mut config = CaptureConfig::new(path, CaptureBits::all());
1094                         if let Some((scene_id, frame_id)) = ids {
1095                             config.scene_id = scene_id;
1096                             config.frame_id = frame_id;
1097                         }
1098 
1099                         self.load_capture(config);
1100 
1101                         for (id, doc) in &self.documents {
1102                             let captured = CapturedDocument {
1103                                 document_id: *id,
1104                                 root_pipeline_id: doc.loaded_scene.root_pipeline_id,
1105                             };
1106                             tx.send(captured).unwrap();
1107                         }
1108 
1109                         // Note: we can't pass `LoadCapture` here since it needs to arrive
1110                         // before the `PublishDocument` messages sent by `load_capture`.
1111                         return RenderBackendStatus::Continue;
1112                     }
1113                     DebugCommand::ClearCaches(mask) => {
1114                         self.resource_cache.clear(mask);
1115                         return RenderBackendStatus::Continue;
1116                     }
1117                     DebugCommand::EnableNativeCompositor(enable) => {
1118                         // Default CompositorKind should be Native
1119                         if let CompositorKind::Draw { .. } = self.default_compositor_kind {
1120                             unreachable!();
1121                         }
1122 
1123                         let compositor_kind = if enable {
1124                             self.default_compositor_kind
1125                         } else {
1126                             CompositorKind::default()
1127                         };
1128 
1129                         for (_, doc) in &mut self.documents {
1130                             doc.scene.config.compositor_kind = compositor_kind;
1131                             doc.frame_is_valid = false;
1132                         }
1133 
1134                         self.frame_config.compositor_kind = compositor_kind;
1135                         self.update_frame_builder_config();
1136 
1137                         // We don't want to forward this message to the renderer.
1138                         return RenderBackendStatus::Continue;
1139                     }
1140                     DebugCommand::EnableMultithreading(enable) => {
1141                         self.resource_cache.enable_multithreading(enable);
1142                         return RenderBackendStatus::Continue;
1143                     }
1144                     DebugCommand::SetBatchingLookback(count) => {
1145                         self.frame_config.batch_lookback_count = count as usize;
1146                         self.update_frame_builder_config();
1147 
1148                         return RenderBackendStatus::Continue;
1149                     }
1150                     DebugCommand::SimulateLongSceneBuild(time_ms) => {
1151                         let _ = self.scene_tx.send(SceneBuilderRequest::SimulateLongSceneBuild(time_ms));
1152                         return RenderBackendStatus::Continue;
1153                     }
1154                     DebugCommand::SetFlags(flags) => {
1155                         self.resource_cache.set_debug_flags(flags);
1156                         self.gpu_cache.set_debug_flags(flags);
1157 
1158                         let force_invalidation = flags.contains(DebugFlags::FORCE_PICTURE_INVALIDATION);
1159                         if self.frame_config.force_invalidation != force_invalidation {
1160                             self.frame_config.force_invalidation = force_invalidation;
1161                             self.update_frame_builder_config();
1162                         }
1163 
1164                         // If we're toggling on the GPU cache debug display, we
1165                         // need to blow away the cache. This is because we only
1166                         // send allocation/free notifications to the renderer
1167                         // thread when the debug display is enabled, and thus
1168                         // enabling it when the cache is partially populated will
1169                         // give the renderer an incomplete view of the world.
1170                         // And since we might as well drop all the debugging state
1171                         // from the renderer when we disable the debug display,
1172                         // we just clear the cache on toggle.
1173                         let changed = self.debug_flags ^ flags;
1174                         if changed.contains(DebugFlags::GPU_CACHE_DBG) {
1175                             self.gpu_cache.clear();
1176                         }
1177                         self.debug_flags = flags;
1178 
1179                         ResultMsg::DebugCommand(option)
1180                     }
1181                     _ => ResultMsg::DebugCommand(option),
1182                 };
1183                 self.result_tx.send(msg).unwrap();
1184                 self.notifier.wake_up(true);
1185             }
1186             ApiMsg::UpdateDocuments(transaction_msgs) => {
1187                 self.prepare_transactions(
1188                     transaction_msgs,
1189                     frame_counter,
1190                 );
1191             }
1192             ApiMsg::SceneBuilderResult(msg) => {
1193                 return self.process_scene_builder_result(msg, frame_counter);
1194             }
1195         }
1196 
1197         RenderBackendStatus::Continue
1198     }
1199 
process_scene_builder_result( &mut self, msg: SceneBuilderResult, frame_counter: &mut u32, ) -> RenderBackendStatus1200     fn process_scene_builder_result(
1201         &mut self,
1202         msg: SceneBuilderResult,
1203         frame_counter: &mut u32,
1204     ) -> RenderBackendStatus {
1205         profile_scope!("sb_msg");
1206 
1207         match msg {
1208             SceneBuilderResult::Transactions(txns, result_tx) => {
1209                 self.process_transaction(
1210                     txns,
1211                     result_tx,
1212                     frame_counter,
1213                 );
1214                 self.bookkeep_after_frames();
1215             },
1216             #[cfg(feature = "capture")]
1217             SceneBuilderResult::CapturedTransactions(txns, capture_config, result_tx) => {
1218                 if let Some(ref mut old_config) = self.capture_config {
1219                     assert!(old_config.scene_id <= capture_config.scene_id);
1220                     if old_config.scene_id < capture_config.scene_id {
1221                         old_config.scene_id = capture_config.scene_id;
1222                         old_config.frame_id = 0;
1223                     }
1224                 } else {
1225                     self.capture_config = Some(capture_config);
1226                 }
1227 
1228                 let built_frame = self.process_transaction(
1229                     txns,
1230                     result_tx,
1231                     frame_counter,
1232                 );
1233 
1234                 if built_frame {
1235                     self.save_capture_sequence();
1236                 }
1237 
1238                 self.bookkeep_after_frames();
1239             },
1240             #[cfg(feature = "capture")]
1241             SceneBuilderResult::StopCaptureSequence => {
1242                 self.capture_config = None;
1243             }
1244             SceneBuilderResult::GetGlyphDimensions(request) => {
1245                 let mut glyph_dimensions = Vec::with_capacity(request.glyph_indices.len());
1246                 if let Some(base) = self.resource_cache.get_font_instance(request.key) {
1247                     let font = FontInstance::from_base(Arc::clone(&base));
1248                     for glyph_index in &request.glyph_indices {
1249                         let glyph_dim = self.resource_cache.get_glyph_dimensions(&font, *glyph_index);
1250                         glyph_dimensions.push(glyph_dim);
1251                     }
1252                 }
1253                 request.sender.send(glyph_dimensions).unwrap();
1254             }
1255             SceneBuilderResult::GetGlyphIndices(request) => {
1256                 let mut glyph_indices = Vec::with_capacity(request.text.len());
1257                 for ch in request.text.chars() {
1258                     let index = self.resource_cache.get_glyph_index(request.key, ch);
1259                     glyph_indices.push(index);
1260                 }
1261                 request.sender.send(glyph_indices).unwrap();
1262             }
1263             SceneBuilderResult::FlushComplete(tx) => {
1264                 tx.send(()).ok();
1265             }
1266             SceneBuilderResult::ExternalEvent(evt) => {
1267                 self.notifier.external_event(evt);
1268             }
1269             SceneBuilderResult::ClearNamespace(id) => {
1270                 self.resource_cache.clear_namespace(id);
1271                 self.documents.retain(|doc_id, _doc| doc_id.namespace_id != id);
1272                 if let Some(handler) = &mut self.blob_image_handler {
1273                     handler.clear_namespace(id);
1274                 }
1275             }
1276             SceneBuilderResult::DeleteDocument(document_id) => {
1277                 self.documents.remove(&document_id);
1278             }
1279             SceneBuilderResult::StopRenderBackend => {
1280                 return RenderBackendStatus::StopRenderBackend;
1281             }
1282             SceneBuilderResult::ShutDown(sender) => {
1283                 info!("Recycling stats: {:?}", self.recycler);
1284                 return RenderBackendStatus::ShutDown(sender);
1285             }
1286         }
1287 
1288         RenderBackendStatus::Continue
1289     }
1290 
update_frame_builder_config(&self)1291     fn update_frame_builder_config(&self) {
1292         self.send_backend_message(
1293             SceneBuilderRequest::SetFrameBuilderConfig(
1294                 self.frame_config.clone()
1295             )
1296         );
1297     }
1298 
prepare_for_frames(&mut self)1299     fn prepare_for_frames(&mut self) {
1300         self.gpu_cache.prepare_for_frames();
1301     }
1302 
bookkeep_after_frames(&mut self)1303     fn bookkeep_after_frames(&mut self) {
1304         self.gpu_cache.bookkeep_after_frames();
1305     }
1306 
requires_frame_build(&mut self) -> bool1307     fn requires_frame_build(&mut self) -> bool {
1308         self.gpu_cache.requires_frame_build()
1309     }
1310 
prepare_transactions( &mut self, txns: Vec<Box<TransactionMsg>>, frame_counter: &mut u32, )1311     fn prepare_transactions(
1312         &mut self,
1313         txns: Vec<Box<TransactionMsg>>,
1314         frame_counter: &mut u32,
1315     ) {
1316         self.prepare_for_frames();
1317         self.maybe_force_nop_documents(
1318             frame_counter,
1319             |document_id| txns.iter().any(|txn| txn.document_id == document_id));
1320 
1321         let mut built_frame = false;
1322         for mut txn in txns {
1323             if txn.generate_frame.as_bool() {
1324                 txn.profile.end_time(profiler::API_SEND_TIME);
1325             }
1326 
1327             self.documents.get_mut(&txn.document_id).unwrap().profile.merge(&mut txn.profile);
1328 
1329             built_frame |= self.update_document(
1330                 txn.document_id,
1331                 txn.resource_updates.take(),
1332                 txn.frame_ops.take(),
1333                 txn.notifications.take(),
1334                 txn.generate_frame.as_bool(),
1335                 txn.generate_frame.id(),
1336                 txn.invalidate_rendered_frame,
1337                 frame_counter,
1338                 false
1339             );
1340         }
1341         if built_frame {
1342             #[cfg(feature = "capture")]
1343             self.save_capture_sequence();
1344         }
1345         self.bookkeep_after_frames();
1346     }
1347 
1348     /// In certain cases, resources shared by multiple documents have to run
1349     /// maintenance operations, like cleaning up unused cache items. In those
1350     /// cases, we are forced to build frames for all documents, however we
1351     /// may not have a transaction ready for every document - this method
1352     /// calls update_document with the details of a fake, nop transaction just
1353     /// to force a frame build.
maybe_force_nop_documents<F>(&mut self, frame_counter: &mut u32, document_already_present: F) where F: Fn(DocumentId) -> bool1354     fn maybe_force_nop_documents<F>(&mut self,
1355                                     frame_counter: &mut u32,
1356                                     document_already_present: F) where
1357         F: Fn(DocumentId) -> bool {
1358         if self.requires_frame_build() {
1359             let nop_documents : Vec<DocumentId> = self.documents.keys()
1360                 .cloned()
1361                 .filter(|key| !document_already_present(*key))
1362                 .collect();
1363             #[allow(unused_variables)]
1364             let mut built_frame = false;
1365             for &document_id in &nop_documents {
1366                 built_frame |= self.update_document(
1367                     document_id,
1368                     Vec::default(),
1369                     Vec::default(),
1370                     Vec::default(),
1371                     false,
1372                     None,
1373                     false,
1374                     frame_counter,
1375                     false);
1376             }
1377             #[cfg(feature = "capture")]
1378             match built_frame {
1379                 true => self.save_capture_sequence(),
1380                 _ => {},
1381             }
1382         }
1383     }
1384 
update_document( &mut self, document_id: DocumentId, resource_updates: Vec<ResourceUpdate>, mut frame_ops: Vec<FrameMsg>, mut notifications: Vec<NotificationRequest>, mut render_frame: bool, generated_frame_id: Option<u64>, invalidate_rendered_frame: bool, frame_counter: &mut u32, has_built_scene: bool, ) -> bool1385     fn update_document(
1386         &mut self,
1387         document_id: DocumentId,
1388         resource_updates: Vec<ResourceUpdate>,
1389         mut frame_ops: Vec<FrameMsg>,
1390         mut notifications: Vec<NotificationRequest>,
1391         mut render_frame: bool,
1392         generated_frame_id: Option<u64>,
1393         invalidate_rendered_frame: bool,
1394         frame_counter: &mut u32,
1395         has_built_scene: bool,
1396     ) -> bool {
1397         let requested_frame = render_frame;
1398 
1399         let requires_frame_build = self.requires_frame_build();
1400         let doc = self.documents.get_mut(&document_id).unwrap();
1401 
1402         // If we have a sampler, get more frame ops from it and add them
1403         // to the transaction. This is a hook to allow the WR user code to
1404         // fiddle with things after a potentially long scene build, but just
1405         // before rendering. This is useful for rendering with the latest
1406         // async transforms.
1407         if requested_frame {
1408             if let Some(ref sampler) = self.sampler {
1409                 frame_ops.append(&mut sampler.sample(document_id, generated_frame_id));
1410             }
1411         }
1412 
1413         doc.has_built_scene |= has_built_scene;
1414 
1415         // TODO: this scroll variable doesn't necessarily mean we scrolled. It is only used
1416         // for something wrench specific and we should remove it.
1417         let mut scroll = false;
1418         for frame_msg in frame_ops {
1419             let op = doc.process_frame_msg(frame_msg);
1420             scroll |= op.scroll;
1421         }
1422 
1423         for update in &resource_updates {
1424             if let ResourceUpdate::UpdateImage(..) = update {
1425                 doc.frame_is_valid = false;
1426             }
1427         }
1428 
1429         self.resource_cache.post_scene_building_update(
1430             resource_updates,
1431             &mut doc.profile,
1432         );
1433 
1434         if doc.dynamic_properties.flush_pending_updates() {
1435             doc.frame_is_valid = false;
1436             doc.hit_tester_is_valid = false;
1437         }
1438 
1439         if !doc.can_render() {
1440             // TODO: this happens if we are building the first scene asynchronously and
1441             // scroll at the same time. we should keep track of the fact that we skipped
1442             // composition here and do it as soon as we receive the scene.
1443             render_frame = false;
1444         }
1445 
1446         // Avoid re-building the frame if the current built frame is still valid.
1447         // However, if the resource_cache requires a frame build, _always_ do that, unless
1448         // doc.can_render() is false, as in that case a frame build can't happen anyway.
1449         // We want to ensure we do this because even if the doc doesn't have pixels it
1450         // can still try to access stale texture cache items.
1451         let build_frame = (render_frame && !doc.frame_is_valid && doc.has_pixels()) ||
1452             (requires_frame_build && doc.can_render());
1453 
1454         // Request composite is true when we want to composite frame even when
1455         // there is no frame update. This happens when video frame is updated under
1456         // external image with NativeTexture or when platform requested to composite frame.
1457         if invalidate_rendered_frame {
1458             doc.rendered_frame_is_valid = false;
1459             if doc.scene.config.compositor_kind.should_redraw_on_invalidation() {
1460                 let msg = ResultMsg::ForceRedraw;
1461                 self.result_tx.send(msg).unwrap();
1462             }
1463         }
1464 
1465         let mut frame_build_time = None;
1466         if build_frame {
1467             profile_scope!("generate frame");
1468 
1469             *frame_counter += 1;
1470 
1471             // borrow ck hack for profile_counters
1472             let (pending_update, mut rendered_document) = {
1473                 let frame_build_start_time = precise_time_ns();
1474 
1475                 let frame_stats = doc.frame_stats.take();
1476 
1477                 let rendered_document = doc.build_frame(
1478                     &mut self.resource_cache,
1479                     &mut self.gpu_cache,
1480                     self.debug_flags,
1481                     &mut self.tile_cache_logger,
1482                     &mut self.tile_caches,
1483                     frame_stats
1484                 );
1485 
1486                 debug!("generated frame for document {:?} with {} passes",
1487                     document_id, rendered_document.frame.passes.len());
1488 
1489                 let msg = ResultMsg::UpdateGpuCache(self.gpu_cache.extract_updates());
1490                 self.result_tx.send(msg).unwrap();
1491 
1492                 frame_build_time = Some(precise_time_ns() - frame_build_start_time);
1493 
1494                 let pending_update = self.resource_cache.pending_updates();
1495                 (pending_update, rendered_document)
1496             };
1497 
1498             // Invalidate dirty rects if the compositing config has changed significantly
1499             rendered_document
1500                 .frame
1501                 .composite_state
1502                 .update_dirty_rect_validity(&doc.prev_composite_descriptor);
1503 
1504             // Build a small struct that represents the state of the tiles to be composited.
1505             let composite_descriptor = rendered_document
1506                 .frame
1507                 .composite_state
1508                 .descriptor
1509                 .clone();
1510 
1511             // If there are texture cache updates to apply, or if the produced
1512             // frame is not a no-op, or the compositor state has changed,
1513             // then we cannot skip compositing this frame.
1514             if !pending_update.is_nop() ||
1515                !rendered_document.frame.is_nop() ||
1516                composite_descriptor != doc.prev_composite_descriptor {
1517                 doc.rendered_frame_is_valid = false;
1518             }
1519             doc.prev_composite_descriptor = composite_descriptor;
1520 
1521             #[cfg(feature = "capture")]
1522             match self.capture_config {
1523                 Some(ref mut config) => {
1524                     // FIXME(aosmond): document splitting causes multiple prepare frames
1525                     config.prepare_frame();
1526 
1527                     if config.bits.contains(CaptureBits::FRAME) {
1528                         let file_name = format!("frame-{}-{}", document_id.namespace_id.0, document_id.id);
1529                         config.serialize_for_frame(&rendered_document.frame, file_name);
1530                     }
1531 
1532                     let data_stores_name = format!("data-stores-{}-{}", document_id.namespace_id.0, document_id.id);
1533                     config.serialize_for_frame(&doc.data_stores, data_stores_name);
1534 
1535                     let properties_name = format!("properties-{}-{}", document_id.namespace_id.0, document_id.id);
1536                     config.serialize_for_frame(&doc.dynamic_properties, properties_name);
1537                 },
1538                 None => {},
1539             }
1540 
1541             let msg = ResultMsg::PublishPipelineInfo(doc.updated_pipeline_info());
1542             self.result_tx.send(msg).unwrap();
1543 
1544             // Publish the frame
1545             let msg = ResultMsg::PublishDocument(
1546                 document_id,
1547                 rendered_document,
1548                 pending_update,
1549             );
1550             self.result_tx.send(msg).unwrap();
1551         } else if requested_frame {
1552             // WR-internal optimization to avoid doing a bunch of render work if
1553             // there's no pixels. We still want to pretend to render and request
1554             // a render to make sure that the callbacks (particularly the
1555             // new_frame_ready callback below) has the right flags.
1556             let msg = ResultMsg::PublishPipelineInfo(doc.updated_pipeline_info());
1557             self.result_tx.send(msg).unwrap();
1558         }
1559 
1560         drain_filter(
1561             &mut notifications,
1562             |n| { n.when() == Checkpoint::FrameBuilt },
1563             |n| { n.notify(); },
1564         );
1565 
1566         if !notifications.is_empty() {
1567             self.result_tx.send(ResultMsg::AppendNotificationRequests(notifications)).unwrap();
1568         }
1569 
1570         // Always forward the transaction to the renderer if a frame was requested,
1571         // otherwise gecko can get into a state where it waits (forever) for the
1572         // transaction to complete before sending new work.
1573         if requested_frame {
1574             // If rendered frame is already valid, there is no need to render frame.
1575             if doc.rendered_frame_is_valid {
1576                 render_frame = false;
1577             } else if render_frame {
1578                 doc.rendered_frame_is_valid = true;
1579             }
1580             self.notifier.new_frame_ready(document_id, scroll, render_frame, frame_build_time);
1581         }
1582 
1583         if !doc.hit_tester_is_valid {
1584             doc.rebuild_hit_tester();
1585         }
1586 
1587         build_frame
1588     }
1589 
send_backend_message(&self, msg: SceneBuilderRequest)1590     fn send_backend_message(&self, msg: SceneBuilderRequest) {
1591         self.scene_tx.send(msg).unwrap();
1592     }
1593 
report_memory(&mut self, tx: Sender<Box<MemoryReport>>)1594     fn report_memory(&mut self, tx: Sender<Box<MemoryReport>>) {
1595         let mut report = Box::new(MemoryReport::default());
1596         let ops = self.size_of_ops.as_mut().unwrap();
1597         let op = ops.size_of_op;
1598         report.gpu_cache_metadata = self.gpu_cache.size_of(ops);
1599         for doc in self.documents.values() {
1600             report.clip_stores += doc.scene.clip_store.size_of(ops);
1601             report.hit_testers += match &doc.hit_tester {
1602                 Some(hit_tester) => hit_tester.size_of(ops),
1603                 None => 0,
1604             };
1605 
1606             doc.data_stores.report_memory(ops, &mut report)
1607         }
1608 
1609         (*report) += self.resource_cache.report_memory(op);
1610         report.texture_cache_structures = self.resource_cache
1611             .texture_cache
1612             .report_memory(ops);
1613 
1614         // Send a message to report memory on the scene-builder thread, which
1615         // will add its report to this one and send the result back to the original
1616         // thread waiting on the request.
1617         self.send_backend_message(
1618             SceneBuilderRequest::ReportMemory(report, tx)
1619         );
1620     }
1621 
1622     #[cfg(feature = "capture")]
save_capture_sequence(&mut self)1623     fn save_capture_sequence(&mut self) {
1624         if let Some(ref mut config) = self.capture_config {
1625             let deferred = self.resource_cache.save_capture_sequence(config);
1626 
1627             let backend = PlainRenderBackend {
1628                 frame_config: self.frame_config.clone(),
1629                 resource_sequence_id: config.resource_id,
1630                 documents: self.documents
1631                     .iter()
1632                     .map(|(id, doc)| (*id, doc.view))
1633                     .collect(),
1634             };
1635             config.serialize_for_frame(&backend, "backend");
1636 
1637             if !deferred.is_empty() {
1638                 let msg = ResultMsg::DebugOutput(DebugOutput::SaveCapture(config.clone(), deferred));
1639                 self.result_tx.send(msg).unwrap();
1640             }
1641         }
1642     }
1643 }
1644 
1645 impl RenderBackend {
1646     #[cfg(feature = "capture")]
1647     // Note: the mutable `self` is only needed here for resolving blob images
save_capture( &mut self, root: PathBuf, bits: CaptureBits, ) -> DebugOutput1648     fn save_capture(
1649         &mut self,
1650         root: PathBuf,
1651         bits: CaptureBits,
1652     ) -> DebugOutput {
1653         use std::fs;
1654         use crate::render_task_graph::dump_render_tasks_as_svg;
1655 
1656         debug!("capture: saving {:?}", root);
1657         if !root.is_dir() {
1658             if let Err(e) = fs::create_dir_all(&root) {
1659                 panic!("Unable to create capture dir: {:?}", e);
1660             }
1661         }
1662         let config = CaptureConfig::new(root, bits);
1663 
1664         if config.bits.contains(CaptureBits::FRAME) {
1665             self.prepare_for_frames();
1666         }
1667 
1668         for (&id, doc) in &mut self.documents {
1669             debug!("\tdocument {:?}", id);
1670             if config.bits.contains(CaptureBits::FRAME) {
1671                 let rendered_document = doc.build_frame(
1672                     &mut self.resource_cache,
1673                     &mut self.gpu_cache,
1674                     self.debug_flags,
1675                     &mut self.tile_cache_logger,
1676                     &mut self.tile_caches,
1677                     None,
1678                 );
1679                 // After we rendered the frames, there are pending updates to both
1680                 // GPU cache and resources. Instead of serializing them, we are going to make sure
1681                 // they are applied on the `Renderer` side.
1682                 let msg_update_gpu_cache = ResultMsg::UpdateGpuCache(self.gpu_cache.extract_updates());
1683                 self.result_tx.send(msg_update_gpu_cache).unwrap();
1684                 //TODO: write down doc's pipeline info?
1685                 // it has `pipeline_epoch_map`,
1686                 // which may capture necessary details for some cases.
1687                 let file_name = format!("frame-{}-{}", id.namespace_id.0, id.id);
1688                 config.serialize_for_frame(&rendered_document.frame, file_name);
1689                 let file_name = format!("spatial-{}-{}", id.namespace_id.0, id.id);
1690                 config.serialize_tree_for_frame(&doc.scene.spatial_tree, file_name);
1691                 let file_name = format!("built-primitives-{}-{}", id.namespace_id.0, id.id);
1692                 config.serialize_for_frame(&doc.scene.prim_store, file_name);
1693                 let file_name = format!("built-clips-{}-{}", id.namespace_id.0, id.id);
1694                 config.serialize_for_frame(&doc.scene.clip_store, file_name);
1695                 let file_name = format!("scratch-{}-{}", id.namespace_id.0, id.id);
1696                 config.serialize_for_frame(&doc.scratch.primitive, file_name);
1697                 let file_name = format!("render-tasks-{}-{}.svg", id.namespace_id.0, id.id);
1698                 let mut render_tasks_file = fs::File::create(&config.file_path_for_frame(file_name, "svg"))
1699                     .expect("Failed to open the SVG file.");
1700                 dump_render_tasks_as_svg(
1701                     &rendered_document.frame.render_tasks,
1702                     &mut render_tasks_file
1703                 ).unwrap();
1704 
1705                 let file_name = format!("texture-cache-color-linear-{}-{}.svg", id.namespace_id.0, id.id);
1706                 let mut texture_file = fs::File::create(&config.file_path_for_frame(file_name, "svg"))
1707                     .expect("Failed to open the SVG file.");
1708                 self.resource_cache.texture_cache.dump_color8_linear_as_svg(&mut texture_file).unwrap();
1709 
1710                 let file_name = format!("texture-cache-color8-glyphs-{}-{}.svg", id.namespace_id.0, id.id);
1711                 let mut texture_file = fs::File::create(&config.file_path_for_frame(file_name, "svg"))
1712                     .expect("Failed to open the SVG file.");
1713                 self.resource_cache.texture_cache.dump_color8_glyphs_as_svg(&mut texture_file).unwrap();
1714 
1715                 let file_name = format!("texture-cache-alpha8-glyphs-{}-{}.svg", id.namespace_id.0, id.id);
1716                 let mut texture_file = fs::File::create(&config.file_path_for_frame(file_name, "svg"))
1717                     .expect("Failed to open the SVG file.");
1718                 self.resource_cache.texture_cache.dump_alpha8_glyphs_as_svg(&mut texture_file).unwrap();
1719 
1720                 let file_name = format!("texture-cache-alpha8-linear-{}-{}.svg", id.namespace_id.0, id.id);
1721                 let mut texture_file = fs::File::create(&config.file_path_for_frame(file_name, "svg"))
1722                     .expect("Failed to open the SVG file.");
1723                 self.resource_cache.texture_cache.dump_alpha8_linear_as_svg(&mut texture_file).unwrap();
1724             }
1725 
1726             let data_stores_name = format!("data-stores-{}-{}", id.namespace_id.0, id.id);
1727             config.serialize_for_frame(&doc.data_stores, data_stores_name);
1728 
1729             let properties_name = format!("properties-{}-{}", id.namespace_id.0, id.id);
1730             config.serialize_for_frame(&doc.dynamic_properties, properties_name);
1731         }
1732 
1733         if config.bits.contains(CaptureBits::FRAME) {
1734             // TODO: there is no guarantee that we won't hit this case, but we want to
1735             // report it here if we do. If we don't, it will simply crash in
1736             // Renderer::render_impl and give us less information about the source.
1737             assert!(!self.requires_frame_build(), "Caches were cleared during a capture.");
1738             self.bookkeep_after_frames();
1739         }
1740 
1741         debug!("\tscene builder");
1742         self.send_backend_message(
1743             SceneBuilderRequest::SaveScene(config.clone())
1744         );
1745 
1746         debug!("\tresource cache");
1747         let (resources, deferred) = self.resource_cache.save_capture(&config.root);
1748 
1749         if config.bits.contains(CaptureBits::TILE_CACHE) {
1750             debug!("\ttile cache");
1751             self.tile_cache_logger.save_capture(&config.root);
1752         }
1753 
1754         info!("\tbackend");
1755         let backend = PlainRenderBackend {
1756             frame_config: self.frame_config.clone(),
1757             resource_sequence_id: 0,
1758             documents: self.documents
1759                 .iter()
1760                 .map(|(id, doc)| (*id, doc.view))
1761                 .collect(),
1762         };
1763 
1764         config.serialize_for_frame(&backend, "backend");
1765         config.serialize_for_frame(&resources, "plain-resources");
1766 
1767         if config.bits.contains(CaptureBits::FRAME) {
1768             let msg_update_resources = ResultMsg::UpdateResources {
1769                 resource_updates: self.resource_cache.pending_updates(),
1770                 memory_pressure: false,
1771             };
1772             self.result_tx.send(msg_update_resources).unwrap();
1773             // Save the texture/glyph/image caches.
1774             info!("\tresource cache");
1775             let caches = self.resource_cache.save_caches(&config.root);
1776             config.serialize_for_resource(&caches, "resource_cache");
1777             info!("\tgpu cache");
1778             config.serialize_for_resource(&self.gpu_cache, "gpu_cache");
1779         }
1780 
1781         DebugOutput::SaveCapture(config, deferred)
1782     }
1783 
1784     #[cfg(feature = "capture")]
start_capture_sequence( &mut self, root: PathBuf, bits: CaptureBits, )1785     fn start_capture_sequence(
1786         &mut self,
1787         root: PathBuf,
1788         bits: CaptureBits,
1789     ) {
1790         self.send_backend_message(
1791             SceneBuilderRequest::StartCaptureSequence(CaptureConfig::new(root, bits))
1792         );
1793     }
1794 
1795     #[cfg(feature = "capture")]
stop_capture_sequence( &mut self, )1796     fn stop_capture_sequence(
1797         &mut self,
1798     ) {
1799         self.send_backend_message(
1800             SceneBuilderRequest::StopCaptureSequence
1801         );
1802     }
1803 
1804     #[cfg(feature = "replay")]
load_capture( &mut self, mut config: CaptureConfig, )1805     fn load_capture(
1806         &mut self,
1807         mut config: CaptureConfig,
1808     ) {
1809         debug!("capture: loading {:?}", config.frame_root());
1810         let backend = config.deserialize_for_frame::<PlainRenderBackend, _>("backend")
1811             .expect("Unable to open backend.ron");
1812 
1813         // If this is a capture sequence, then the ID will be non-zero, and won't
1814         // match what is loaded, but for still captures, the ID will be zero.
1815         let first_load = backend.resource_sequence_id == 0;
1816         if self.loaded_resource_sequence_id != backend.resource_sequence_id || first_load {
1817             // FIXME(aosmond): We clear the documents because when we update the
1818             // resource cache, we actually wipe and reload, because we don't
1819             // know what is the same and what has changed. If we were to keep as
1820             // much of the resource cache state as possible, we could avoid
1821             // flushing the document state (which has its own dependecies on the
1822             // cache).
1823             //
1824             // FIXME(aosmond): If we try to load the next capture in the
1825             // sequence too quickly, we may lose resources we depend on in the
1826             // current frame. This can cause panics. Ideally we would not
1827             // advance to the next frame until the FrameRendered event for all
1828             // of the pipelines.
1829             self.documents.clear();
1830 
1831             config.resource_id = backend.resource_sequence_id;
1832             self.loaded_resource_sequence_id = backend.resource_sequence_id;
1833 
1834             let plain_resources = config.deserialize_for_resource::<PlainResources, _>("plain-resources")
1835                 .expect("Unable to open plain-resources.ron");
1836             let caches_maybe = config.deserialize_for_resource::<PlainCacheOwn, _>("resource_cache");
1837 
1838             // Note: it would be great to have `RenderBackend` to be split
1839             // rather explicitly on what's used before and after scene building
1840             // so that, for example, we never miss anything in the code below:
1841 
1842             let plain_externals = self.resource_cache.load_capture(
1843                 plain_resources,
1844                 caches_maybe,
1845                 &config,
1846             );
1847 
1848             let msg_load = ResultMsg::DebugOutput(
1849                 DebugOutput::LoadCapture(config.clone(), plain_externals)
1850             );
1851             self.result_tx.send(msg_load).unwrap();
1852 
1853             self.gpu_cache = match config.deserialize_for_resource::<GpuCache, _>("gpu_cache") {
1854                 Some(gpu_cache) => gpu_cache,
1855                 None => GpuCache::new(),
1856             };
1857         }
1858 
1859         self.frame_config = backend.frame_config;
1860 
1861         let mut scenes_to_build = Vec::new();
1862 
1863         for (id, view) in backend.documents {
1864             debug!("\tdocument {:?}", id);
1865             let scene_name = format!("scene-{}-{}", id.namespace_id.0, id.id);
1866             let scene = config.deserialize_for_scene::<Scene, _>(&scene_name)
1867                 .expect(&format!("Unable to open {}.ron", scene_name));
1868 
1869             let interners_name = format!("interners-{}-{}", id.namespace_id.0, id.id);
1870             let interners = config.deserialize_for_scene::<Interners, _>(&interners_name)
1871                 .expect(&format!("Unable to open {}.ron", interners_name));
1872 
1873             let data_stores_name = format!("data-stores-{}-{}", id.namespace_id.0, id.id);
1874             let data_stores = config.deserialize_for_frame::<DataStores, _>(&data_stores_name)
1875                 .expect(&format!("Unable to open {}.ron", data_stores_name));
1876 
1877             let properties_name = format!("properties-{}-{}", id.namespace_id.0, id.id);
1878             let properties = config.deserialize_for_frame::<SceneProperties, _>(&properties_name)
1879                 .expect(&format!("Unable to open {}.ron", properties_name));
1880 
1881             // Update the document if it still exists, rather than replace it entirely.
1882             // This allows us to preserve state information such as the frame stamp,
1883             // which is necessary for cache sanity.
1884             match self.documents.entry(id) {
1885                 Occupied(entry) => {
1886                     let doc = entry.into_mut();
1887                     doc.view = view;
1888                     doc.loaded_scene = scene.clone();
1889                     doc.data_stores = data_stores;
1890                     doc.dynamic_properties = properties;
1891                     doc.frame_is_valid = false;
1892                     doc.rendered_frame_is_valid = false;
1893                     doc.has_built_scene = false;
1894                     doc.hit_tester_is_valid = false;
1895                 }
1896                 Vacant(entry) => {
1897                     let doc = Document {
1898                         id,
1899                         scene: BuiltScene::empty(),
1900                         removed_pipelines: Vec::new(),
1901                         view,
1902                         stamp: FrameStamp::first(id),
1903                         frame_builder: FrameBuilder::new(),
1904                         dynamic_properties: properties,
1905                         hit_tester: None,
1906                         shared_hit_tester: Arc::new(SharedHitTester::new()),
1907                         frame_is_valid: false,
1908                         hit_tester_is_valid: false,
1909                         rendered_frame_is_valid: false,
1910                         has_built_scene: false,
1911                         data_stores,
1912                         scratch: ScratchBuffer::default(),
1913                         loaded_scene: scene.clone(),
1914                         prev_composite_descriptor: CompositeDescriptor::empty(),
1915                         dirty_rects_are_valid: false,
1916                         profile: TransactionProfile::new(),
1917                         rg_builder: RenderTaskGraphBuilder::new(),
1918                         frame_stats: None,
1919                     };
1920                     entry.insert(doc);
1921                 }
1922             };
1923 
1924             let frame_name = format!("frame-{}-{}", id.namespace_id.0, id.id);
1925             let frame = config.deserialize_for_frame::<Frame, _>(frame_name);
1926             let build_frame = match frame {
1927                 Some(frame) => {
1928                     info!("\tloaded a built frame with {} passes", frame.passes.len());
1929 
1930                     let msg_update = ResultMsg::UpdateGpuCache(self.gpu_cache.extract_updates());
1931                     self.result_tx.send(msg_update).unwrap();
1932 
1933                     let msg_publish = ResultMsg::PublishDocument(
1934                         id,
1935                         RenderedDocument { frame, is_new_scene: true, profile: TransactionProfile::new(), frame_stats: None },
1936                         self.resource_cache.pending_updates(),
1937                     );
1938                     self.result_tx.send(msg_publish).unwrap();
1939 
1940                     self.notifier.new_frame_ready(id, false, true, None);
1941 
1942                     // We deserialized the state of the frame so we don't want to build
1943                     // it (but we do want to update the scene builder's state)
1944                     false
1945                 }
1946                 None => true,
1947             };
1948 
1949             scenes_to_build.push(LoadScene {
1950                 document_id: id,
1951                 scene,
1952                 view: view.scene.clone(),
1953                 config: self.frame_config.clone(),
1954                 font_instances: self.resource_cache.get_font_instances(),
1955                 build_frame,
1956                 interners,
1957             });
1958         }
1959 
1960         if !scenes_to_build.is_empty() {
1961             self.send_backend_message(
1962                 SceneBuilderRequest::LoadScenes(scenes_to_build)
1963             );
1964         }
1965     }
1966 }
1967