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 #![deny(missing_docs)]
6 
7 use std::cell::Cell;
8 use std::fmt;
9 use std::marker::PhantomData;
10 use std::path::PathBuf;
11 use std::sync::Arc;
12 use std::u32;
13 use time::precise_time_ns;
14 //use crate::api::peek_poke::PeekPoke;
15 use crate::api::channel::{Sender, single_msg_channel, unbounded_channel};
16 use crate::api::{ColorF, BuiltDisplayList, IdNamespace, ExternalScrollId};
17 use crate::api::{SharedFontInstanceMap, FontKey, FontInstanceKey, NativeFontHandle};
18 use crate::api::{BlobImageData, BlobImageKey, ImageData, ImageDescriptor, ImageKey, Epoch, QualitySettings};
19 use crate::api::{BlobImageParams, BlobImageRequest, BlobImageResult, AsyncBlobImageRasterizer, BlobImageHandler};
20 use crate::api::{DocumentId, PipelineId, PropertyBindingId, PropertyBindingKey, ExternalEvent};
21 use crate::api::{HitTestResult, HitTesterRequest, ApiHitTester, PropertyValue, DynamicProperties};
22 use crate::api::{ScrollClamping, TileSize, NotificationRequest, DebugFlags, ScrollNodeState};
23 use crate::api::{GlyphDimensionRequest, GlyphIndexRequest, GlyphIndex, GlyphDimensions};
24 use crate::api::{FontInstanceOptions, FontInstancePlatformOptions, FontVariation};
25 use crate::api::DEFAULT_TILE_SIZE;
26 use crate::api::units::*;
27 use crate::api_resources::ApiResources;
28 use crate::scene_builder_thread::{SceneBuilderRequest, SceneBuilderResult};
29 use crate::intern::InterningMemoryReport;
30 use crate::profiler::{self, TransactionProfile};
31 
32 #[repr(C)]
33 #[derive(Clone, Copy, Debug)]
34 #[cfg_attr(any(feature = "serde"), derive(Deserialize, Serialize))]
35 struct ResourceId(pub u32);
36 
37 /// Update of a persistent resource in WebRender.
38 ///
39 /// ResourceUpdate changes keep theirs effect across display list changes.
40 #[derive(Clone)]
41 #[cfg_attr(any(feature = "serde"), derive(Deserialize, Serialize))]
42 pub enum ResourceUpdate {
43     /// See `AddImage`.
44     AddImage(AddImage),
45     /// See `UpdateImage`.
46     UpdateImage(UpdateImage),
47     /// Delete an existing image resource.
48     ///
49     /// It is invalid to continue referring to the image key in any display list
50     /// in the transaction that contains the `DeleteImage` message and subsequent
51     /// transactions.
52     DeleteImage(ImageKey),
53     /// See `AddBlobImage`.
54     AddBlobImage(AddBlobImage),
55     /// See `UpdateBlobImage`.
56     UpdateBlobImage(UpdateBlobImage),
57     /// Delete existing blob image resource.
58     DeleteBlobImage(BlobImageKey),
59     /// See `AddBlobImage::visible_area`.
60     SetBlobImageVisibleArea(BlobImageKey, DeviceIntRect),
61     /// See `AddFont`.
62     AddFont(AddFont),
63     /// Deletes an already existing font resource.
64     ///
65     /// It is invalid to continue referring to the font key in any display list
66     /// in the transaction that contains the `DeleteImage` message and subsequent
67     /// transactions.
68     DeleteFont(FontKey),
69     /// See `AddFontInstance`.
70     AddFontInstance(AddFontInstance),
71     /// Deletes an already existing font instance resource.
72     ///
73     /// It is invalid to continue referring to the font instance in any display
74     /// list in the transaction that contains the `DeleteImage` message and
75     /// subsequent transactions.
76     DeleteFontInstance(FontInstanceKey),
77 }
78 
79 impl fmt::Debug for ResourceUpdate {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result80     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
81         match self {
82             ResourceUpdate::AddImage(ref i) => f.write_fmt(format_args!(
83                 "ResourceUpdate::AddImage size({:?})",
84                 &i.descriptor.size
85             )),
86             ResourceUpdate::UpdateImage(ref i) => f.write_fmt(format_args!(
87                 "ResourceUpdate::UpdateImage size({:?})",
88                 &i.descriptor.size
89             )),
90             ResourceUpdate::AddBlobImage(ref i) => f.write_fmt(format_args!(
91                 "ResourceUFpdate::AddBlobImage size({:?})",
92                 &i.descriptor.size
93             )),
94             ResourceUpdate::UpdateBlobImage(i) => f.write_fmt(format_args!(
95                 "ResourceUpdate::UpdateBlobImage size({:?})",
96                 &i.descriptor.size
97             )),
98             ResourceUpdate::DeleteImage(..) => f.write_str("ResourceUpdate::DeleteImage"),
99             ResourceUpdate::DeleteBlobImage(..) => f.write_str("ResourceUpdate::DeleteBlobImage"),
100             ResourceUpdate::SetBlobImageVisibleArea(..) => f.write_str("ResourceUpdate::SetBlobImageVisibleArea"),
101             ResourceUpdate::AddFont(..) => f.write_str("ResourceUpdate::AddFont"),
102             ResourceUpdate::DeleteFont(..) => f.write_str("ResourceUpdate::DeleteFont"),
103             ResourceUpdate::AddFontInstance(..) => f.write_str("ResourceUpdate::AddFontInstance"),
104             ResourceUpdate::DeleteFontInstance(..) => f.write_str("ResourceUpdate::DeleteFontInstance"),
105         }
106     }
107 }
108 
109 /// Whether to generate a frame, and if so, an id that allows tracking this
110 /// transaction through the various frame stages.
111 #[derive(Clone, Debug)]
112 pub enum GenerateFrame {
113     /// Generate a frame if something changed.
114     Yes {
115         /// An id that allows tracking the frame transaction through the various
116         /// frame stages. Specified by the caller of generate_frame().
117         id: u64,
118     },
119     /// Don't generate a frame even if something has changed.
120     No,
121 }
122 
123 impl GenerateFrame {
124     ///
as_bool(&self) -> bool125     pub fn as_bool(&self) -> bool {
126         match self {
127             GenerateFrame::Yes { .. } => true,
128             GenerateFrame::No => false,
129         }
130     }
131 
132     /// Return the frame ID, if a frame is generated.
id(&self) -> Option<u64>133     pub fn id(&self) -> Option<u64> {
134         match self {
135             GenerateFrame::Yes { id } => Some(*id),
136             GenerateFrame::No => None,
137         }
138     }
139 }
140 
141 /// A Transaction is a group of commands to apply atomically to a document.
142 ///
143 /// This mechanism ensures that:
144 ///  - no other message can be interleaved between two commands that need to be applied together.
145 ///  - no redundant work is performed if two commands in the same transaction cause the scene or
146 ///    the frame to be rebuilt.
147 pub struct Transaction {
148     /// Operations affecting the scene (applied before scene building).
149     scene_ops: Vec<SceneMsg>,
150     /// Operations affecting the generation of frames (applied after scene building).
151     frame_ops: Vec<FrameMsg>,
152 
153     notifications: Vec<NotificationRequest>,
154 
155     /// Persistent resource updates to apply as part of this transaction.
156     pub resource_updates: Vec<ResourceUpdate>,
157 
158     /// True if the transaction needs the scene building thread's attention.
159     /// False for things that can skip the scene builder, like APZ changes and
160     /// async images.
161     ///
162     /// Before this `Transaction` is converted to a `TransactionMsg`, we look
163     /// over its contents and set this if we're doing anything the scene builder
164     /// needs to know about, so this is only a default.
165     use_scene_builder_thread: bool,
166 
167     /// Whether to generate a frame, and if so, an id that allows tracking this
168     /// transaction through the various frame stages. Specified by the caller of
169     /// generate_frame().
170     generate_frame: GenerateFrame,
171 
172     /// Set to true in order to force re-rendering even if WebRender can't internally
173     /// detect that something has changed.
174     pub invalidate_rendered_frame: bool,
175 
176     low_priority: bool,
177 }
178 
179 impl Transaction {
180     /// Constructor.
new() -> Self181     pub fn new() -> Self {
182         Transaction {
183             scene_ops: Vec::new(),
184             frame_ops: Vec::new(),
185             resource_updates: Vec::new(),
186             notifications: Vec::new(),
187             use_scene_builder_thread: true,
188             generate_frame: GenerateFrame::No,
189             invalidate_rendered_frame: false,
190             low_priority: false,
191         }
192     }
193 
194     /// Marks this transaction to allow it to skip going through the scene builder
195     /// thread.
196     ///
197     /// This is useful to avoid jank in transaction associated with animated
198     /// property updates, panning and zooming.
199     ///
200     /// Note that transactions that skip the scene builder thread can race ahead of
201     /// transactions that don't skip it.
skip_scene_builder(&mut self)202     pub fn skip_scene_builder(&mut self) {
203         self.use_scene_builder_thread = false;
204     }
205 
206     /// Marks this transaction to enforce going through the scene builder thread.
use_scene_builder_thread(&mut self)207     pub fn use_scene_builder_thread(&mut self) {
208         self.use_scene_builder_thread = true;
209     }
210 
211     /// Returns true if the transaction has no effect.
is_empty(&self) -> bool212     pub fn is_empty(&self) -> bool {
213         !self.generate_frame.as_bool() &&
214             !self.invalidate_rendered_frame &&
215             self.scene_ops.is_empty() &&
216             self.frame_ops.is_empty() &&
217             self.resource_updates.is_empty() &&
218             self.notifications.is_empty()
219     }
220 
221     /// Update a pipeline's epoch.
update_epoch(&mut self, pipeline_id: PipelineId, epoch: Epoch)222     pub fn update_epoch(&mut self, pipeline_id: PipelineId, epoch: Epoch) {
223         // We track epochs before and after scene building.
224         // This one will be applied to the pending scene right away:
225         self.scene_ops.push(SceneMsg::UpdateEpoch(pipeline_id, epoch));
226         // And this one will be applied to the currently built scene at the end
227         // of the transaction (potentially long after the scene_ops one).
228         self.frame_ops.push(FrameMsg::UpdateEpoch(pipeline_id, epoch));
229         // We could avoid the duplication here by storing the epoch updates in a
230         // separate array and let the render backend schedule the updates at the
231         // proper times, but it wouldn't make things simpler.
232     }
233 
234     /// Sets the root pipeline.
235     ///
236     /// # Examples
237     ///
238     /// ```
239     /// # use webrender::api::{PipelineId};
240     /// # use webrender::api::units::{DeviceIntSize};
241     /// # use webrender::render_api::{RenderApiSender, Transaction};
242     /// # fn example() {
243     /// let pipeline_id = PipelineId(0, 0);
244     /// let mut txn = Transaction::new();
245     /// txn.set_root_pipeline(pipeline_id);
246     /// # }
247     /// ```
set_root_pipeline(&mut self, pipeline_id: PipelineId)248     pub fn set_root_pipeline(&mut self, pipeline_id: PipelineId) {
249         self.scene_ops.push(SceneMsg::SetRootPipeline(pipeline_id));
250     }
251 
252     /// Removes data associated with a pipeline from the internal data structures.
253     /// If the specified `pipeline_id` is for the root pipeline, the root pipeline
254     /// is reset back to `None`.
remove_pipeline(&mut self, pipeline_id: PipelineId)255     pub fn remove_pipeline(&mut self, pipeline_id: PipelineId) {
256         self.scene_ops.push(SceneMsg::RemovePipeline(pipeline_id));
257     }
258 
259     /// Supplies a new frame to WebRender.
260     ///
261     /// Non-blocking, it notifies a worker process which processes the display list.
262     ///
263     /// Note: Scrolling doesn't require an own Frame.
264     ///
265     /// Arguments:
266     ///
267     /// * `epoch`: The unique Frame ID, monotonically increasing.
268     /// * `background`: The background color of this pipeline.
269     /// * `viewport_size`: The size of the viewport for this frame.
270     /// * `pipeline_id`: The ID of the pipeline that is supplying this display list.
271     /// * `display_list`: The root Display list used in this frame.
272     /// * `preserve_frame_state`: If a previous frame exists which matches this pipeline
273     ///                           id, this setting determines if frame state (such as scrolling
274     ///                           position) should be preserved for this new display list.
set_display_list( &mut self, epoch: Epoch, background: Option<ColorF>, viewport_size: LayoutSize, (pipeline_id, mut display_list): (PipelineId, BuiltDisplayList), preserve_frame_state: bool, )275     pub fn set_display_list(
276         &mut self,
277         epoch: Epoch,
278         background: Option<ColorF>,
279         viewport_size: LayoutSize,
280         (pipeline_id, mut display_list): (PipelineId, BuiltDisplayList),
281         preserve_frame_state: bool,
282     ) {
283         display_list.set_send_time_ns(precise_time_ns());
284         self.scene_ops.push(
285             SceneMsg::SetDisplayList {
286                 display_list,
287                 epoch,
288                 pipeline_id,
289                 background,
290                 viewport_size,
291                 preserve_frame_state,
292             }
293         );
294     }
295 
296     /// Add a set of persistent resource updates to apply as part of this transaction.
update_resources(&mut self, mut resources: Vec<ResourceUpdate>)297     pub fn update_resources(&mut self, mut resources: Vec<ResourceUpdate>) {
298         self.resource_updates.append(&mut resources);
299     }
300 
301     // Note: Gecko uses this to get notified when a transaction that contains
302     // potentially long blob rasterization or scene build is ready to be rendered.
303     // so that the tab-switching integration can react adequately when tab
304     // switching takes too long. For this use case when matters is that the
305     // notification doesn't fire before scene building and blob rasterization.
306 
307     /// Trigger a notification at a certain stage of the rendering pipeline.
308     ///
309     /// Not that notification requests are skipped during serialization, so is is
310     /// best to use them for synchronization purposes and not for things that could
311     /// affect the WebRender's state.
notify(&mut self, event: NotificationRequest)312     pub fn notify(&mut self, event: NotificationRequest) {
313         self.notifications.push(event);
314     }
315 
316     /// Setup the output region in the framebuffer for a given document.
set_document_view( &mut self, device_rect: DeviceIntRect, )317     pub fn set_document_view(
318         &mut self,
319         device_rect: DeviceIntRect,
320     ) {
321         window_size_sanity_check(device_rect.size());
322         self.scene_ops.push(
323             SceneMsg::SetDocumentView {
324                 device_rect,
325             },
326         );
327     }
328 
329     /// Scrolls the node identified by the given external scroll id to the
330     /// given scroll position, relative to the pre-scrolled offset for the
331     /// scrolling layer. That is, providing an origin of (0,0) will reset
332     /// any WR-side scrolling and just render the display items at the
333     /// pre-scrolled offsets as provided in the display list. Larger `origin`
334     /// values will cause the layer to be scrolled further towards the end of
335     /// the scroll range.
336     /// If the ScrollClamping argument is set to clamp, the scroll position
337     /// is clamped to what WebRender understands to be the bounds of the
338     /// scroll range, based on the sizes of the scrollable content and the
339     /// scroll port.
scroll_node_with_id( &mut self, origin: LayoutPoint, id: ExternalScrollId, clamp: ScrollClamping, )340     pub fn scroll_node_with_id(
341         &mut self,
342         origin: LayoutPoint,
343         id: ExternalScrollId,
344         clamp: ScrollClamping,
345     ) {
346         self.frame_ops.push(FrameMsg::ScrollNodeWithId(origin, id, clamp));
347     }
348 
349     /// Set the current quality / performance settings for this document.
set_quality_settings(&mut self, settings: QualitySettings)350     pub fn set_quality_settings(&mut self, settings: QualitySettings) {
351         self.scene_ops.push(SceneMsg::SetQualitySettings { settings });
352     }
353 
354     ///
set_is_transform_async_zooming(&mut self, is_zooming: bool, animation_id: PropertyBindingId)355     pub fn set_is_transform_async_zooming(&mut self, is_zooming: bool, animation_id: PropertyBindingId) {
356         self.frame_ops.push(FrameMsg::SetIsTransformAsyncZooming(is_zooming, animation_id));
357     }
358 
359     /// Generate a new frame. When it's done and a RenderNotifier has been set
360     /// in `webrender::Renderer`, [new_frame_ready()][notifier] gets called.
361     /// Note that the notifier is called even if the frame generation was a
362     /// no-op; the arguments passed to `new_frame_ready` will provide information
363     /// as to when happened.
364     ///
365     /// [notifier]: trait.RenderNotifier.html#tymethod.new_frame_ready
generate_frame(&mut self, id: u64)366     pub fn generate_frame(&mut self, id: u64) {
367         self.generate_frame = GenerateFrame::Yes{ id };
368     }
369 
370     /// Invalidate rendered frame. It ensure that frame will be rendered during
371     /// next frame generation. WebRender could skip frame rendering if there
372     /// is no update.
373     /// But there are cases that needs to force rendering.
374     ///  - Content of image is updated by reusing same ExternalImageId.
375     ///  - Platform requests it if pixels become stale (like wakeup from standby).
invalidate_rendered_frame(&mut self)376     pub fn invalidate_rendered_frame(&mut self) {
377         self.invalidate_rendered_frame = true;
378     }
379 
380     /// Supply a list of animated property bindings that should be used to resolve
381     /// bindings in the current display list.
update_dynamic_properties(&mut self, properties: DynamicProperties)382     pub fn update_dynamic_properties(&mut self, properties: DynamicProperties) {
383         self.frame_ops.push(FrameMsg::UpdateDynamicProperties(properties));
384     }
385 
386     /// Add to the list of animated property bindings that should be used to
387     /// resolve bindings in the current display list. This is a convenience method
388     /// so the caller doesn't have to figure out all the dynamic properties before
389     /// setting them on the transaction but can do them incrementally.
append_dynamic_transform_properties(&mut self, transforms: Vec<PropertyValue<LayoutTransform>>)390     pub fn append_dynamic_transform_properties(&mut self, transforms: Vec<PropertyValue<LayoutTransform>>) {
391         self.frame_ops.push(FrameMsg::AppendDynamicTransformProperties(transforms));
392     }
393 
394     /// Consumes this object and just returns the frame ops.
get_frame_ops(self) -> Vec<FrameMsg>395     pub fn get_frame_ops(self) -> Vec<FrameMsg> {
396         self.frame_ops
397     }
398 
finalize(self, document_id: DocumentId) -> Box<TransactionMsg>399     fn finalize(self, document_id: DocumentId) -> Box<TransactionMsg> {
400         Box::new(TransactionMsg {
401             document_id,
402             scene_ops: self.scene_ops,
403             frame_ops: self.frame_ops,
404             resource_updates: self.resource_updates,
405             notifications: self.notifications,
406             use_scene_builder_thread: self.use_scene_builder_thread,
407             generate_frame: self.generate_frame,
408             invalidate_rendered_frame: self.invalidate_rendered_frame,
409             low_priority: self.low_priority,
410             blob_rasterizer: None,
411             blob_requests: Vec::new(),
412             rasterized_blobs: Vec::new(),
413             profile: TransactionProfile::new(),
414         })
415     }
416 
417     /// See `ResourceUpdate::AddImage`.
add_image( &mut self, key: ImageKey, descriptor: ImageDescriptor, data: ImageData, tiling: Option<TileSize>, )418     pub fn add_image(
419         &mut self,
420         key: ImageKey,
421         descriptor: ImageDescriptor,
422         data: ImageData,
423         tiling: Option<TileSize>,
424     ) {
425         self.resource_updates.push(ResourceUpdate::AddImage(AddImage {
426             key,
427             descriptor,
428             data,
429             tiling,
430         }));
431     }
432 
433     /// See `ResourceUpdate::UpdateImage`.
update_image( &mut self, key: ImageKey, descriptor: ImageDescriptor, data: ImageData, dirty_rect: &ImageDirtyRect, )434     pub fn update_image(
435         &mut self,
436         key: ImageKey,
437         descriptor: ImageDescriptor,
438         data: ImageData,
439         dirty_rect: &ImageDirtyRect,
440     ) {
441         self.resource_updates.push(ResourceUpdate::UpdateImage(UpdateImage {
442             key,
443             descriptor,
444             data,
445             dirty_rect: *dirty_rect,
446         }));
447     }
448 
449     /// See `ResourceUpdate::DeleteImage`.
delete_image(&mut self, key: ImageKey)450     pub fn delete_image(&mut self, key: ImageKey) {
451         self.resource_updates.push(ResourceUpdate::DeleteImage(key));
452     }
453 
454     /// See `ResourceUpdate::AddBlobImage`.
add_blob_image( &mut self, key: BlobImageKey, descriptor: ImageDescriptor, data: Arc<BlobImageData>, visible_rect: DeviceIntRect, tile_size: Option<TileSize>, )455     pub fn add_blob_image(
456         &mut self,
457         key: BlobImageKey,
458         descriptor: ImageDescriptor,
459         data: Arc<BlobImageData>,
460         visible_rect: DeviceIntRect,
461         tile_size: Option<TileSize>,
462     ) {
463         self.resource_updates.push(
464             ResourceUpdate::AddBlobImage(AddBlobImage {
465                 key,
466                 descriptor,
467                 data,
468                 visible_rect,
469                 tile_size: tile_size.unwrap_or(DEFAULT_TILE_SIZE),
470             })
471         );
472     }
473 
474     /// See `ResourceUpdate::UpdateBlobImage`.
update_blob_image( &mut self, key: BlobImageKey, descriptor: ImageDescriptor, data: Arc<BlobImageData>, visible_rect: DeviceIntRect, dirty_rect: &BlobDirtyRect, )475     pub fn update_blob_image(
476         &mut self,
477         key: BlobImageKey,
478         descriptor: ImageDescriptor,
479         data: Arc<BlobImageData>,
480         visible_rect: DeviceIntRect,
481         dirty_rect: &BlobDirtyRect,
482     ) {
483         self.resource_updates.push(
484             ResourceUpdate::UpdateBlobImage(UpdateBlobImage {
485                 key,
486                 descriptor,
487                 data,
488                 visible_rect,
489                 dirty_rect: *dirty_rect,
490             })
491         );
492     }
493 
494     /// See `ResourceUpdate::DeleteBlobImage`.
delete_blob_image(&mut self, key: BlobImageKey)495     pub fn delete_blob_image(&mut self, key: BlobImageKey) {
496         self.resource_updates.push(ResourceUpdate::DeleteBlobImage(key));
497     }
498 
499     /// See `ResourceUpdate::SetBlobImageVisibleArea`.
set_blob_image_visible_area(&mut self, key: BlobImageKey, area: DeviceIntRect)500     pub fn set_blob_image_visible_area(&mut self, key: BlobImageKey, area: DeviceIntRect) {
501         self.resource_updates.push(ResourceUpdate::SetBlobImageVisibleArea(key, area));
502     }
503 
504     /// See `ResourceUpdate::AddFont`.
add_raw_font(&mut self, key: FontKey, bytes: Vec<u8>, index: u32)505     pub fn add_raw_font(&mut self, key: FontKey, bytes: Vec<u8>, index: u32) {
506         self.resource_updates
507             .push(ResourceUpdate::AddFont(AddFont::Raw(key, Arc::new(bytes), index)));
508     }
509 
510     /// See `ResourceUpdate::AddFont`.
add_native_font(&mut self, key: FontKey, native_handle: NativeFontHandle)511     pub fn add_native_font(&mut self, key: FontKey, native_handle: NativeFontHandle) {
512         self.resource_updates
513             .push(ResourceUpdate::AddFont(AddFont::Native(key, native_handle)));
514     }
515 
516     /// See `ResourceUpdate::DeleteFont`.
delete_font(&mut self, key: FontKey)517     pub fn delete_font(&mut self, key: FontKey) {
518         self.resource_updates.push(ResourceUpdate::DeleteFont(key));
519     }
520 
521     /// See `ResourceUpdate::AddFontInstance`.
add_font_instance( &mut self, key: FontInstanceKey, font_key: FontKey, glyph_size: f32, options: Option<FontInstanceOptions>, platform_options: Option<FontInstancePlatformOptions>, variations: Vec<FontVariation>, )522     pub fn add_font_instance(
523         &mut self,
524         key: FontInstanceKey,
525         font_key: FontKey,
526         glyph_size: f32,
527         options: Option<FontInstanceOptions>,
528         platform_options: Option<FontInstancePlatformOptions>,
529         variations: Vec<FontVariation>,
530     ) {
531         self.resource_updates
532             .push(ResourceUpdate::AddFontInstance(AddFontInstance {
533                 key,
534                 font_key,
535                 glyph_size,
536                 options,
537                 platform_options,
538                 variations,
539             }));
540     }
541 
542     /// See `ResourceUpdate::DeleteFontInstance`.
delete_font_instance(&mut self, key: FontInstanceKey)543     pub fn delete_font_instance(&mut self, key: FontInstanceKey) {
544         self.resource_updates.push(ResourceUpdate::DeleteFontInstance(key));
545     }
546 
547     /// A hint that this transaction can be processed at a lower priority. High-
548     /// priority transactions can jump ahead of regular-priority transactions,
549     /// but both high- and regular-priority transactions are processed in order
550     /// relative to other transactions of the same priority.
set_low_priority(&mut self, low_priority: bool)551     pub fn set_low_priority(&mut self, low_priority: bool) {
552         self.low_priority = low_priority;
553     }
554 
555     /// Returns whether this transaction is marked as low priority.
is_low_priority(&self) -> bool556     pub fn is_low_priority(&self) -> bool {
557         self.low_priority
558     }
559 }
560 
561 ///
562 pub struct DocumentTransaction {
563     ///
564     pub document_id: DocumentId,
565     ///
566     pub transaction: Transaction,
567 }
568 
569 /// Represents a transaction in the format sent through the channel.
570 pub struct TransactionMsg {
571     ///
572     pub document_id: DocumentId,
573     /// Changes that require re-building the scene.
574     pub scene_ops: Vec<SceneMsg>,
575     /// Changes to animated properties that do not require re-building the scene.
576     pub frame_ops: Vec<FrameMsg>,
577     /// Updates to resources that persist across display lists.
578     pub resource_updates: Vec<ResourceUpdate>,
579     /// Whether to trigger frame building and rendering if something has changed.
580     pub generate_frame: GenerateFrame,
581     /// Whether to force frame building and rendering even if no changes are internally
582     /// observed.
583     pub invalidate_rendered_frame: bool,
584     /// Whether to enforce that this transaction go through the scene builder.
585     pub use_scene_builder_thread: bool,
586     ///
587     pub low_priority: bool,
588 
589     /// Handlers to notify at certain points of the pipeline.
590     pub notifications: Vec<NotificationRequest>,
591     ///
592     pub blob_rasterizer: Option<Box<dyn AsyncBlobImageRasterizer>>,
593     ///
594     pub blob_requests: Vec<BlobImageParams>,
595     ///
596     pub rasterized_blobs: Vec<(BlobImageRequest, BlobImageResult)>,
597     /// Collect various data along the rendering pipeline to display it in the embedded profiler.
598     pub profile: TransactionProfile,
599 }
600 
601 impl fmt::Debug for TransactionMsg {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result602     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
603         writeln!(f, "threaded={}, genframe={:?}, invalidate={}, low_priority={}",
604                         self.use_scene_builder_thread,
605                         self.generate_frame,
606                         self.invalidate_rendered_frame,
607                         self.low_priority,
608                     ).unwrap();
609         for scene_op in &self.scene_ops {
610             writeln!(f, "\t\t{:?}", scene_op).unwrap();
611         }
612 
613         for frame_op in &self.frame_ops {
614             writeln!(f, "\t\t{:?}", frame_op).unwrap();
615         }
616 
617         for resource_update in &self.resource_updates {
618             writeln!(f, "\t\t{:?}", resource_update).unwrap();
619         }
620         Ok(())
621     }
622 }
623 
624 impl TransactionMsg {
625     /// Returns true if this transaction has no effect.
is_empty(&self) -> bool626     pub fn is_empty(&self) -> bool {
627         !self.generate_frame.as_bool() &&
628             !self.invalidate_rendered_frame &&
629             self.scene_ops.is_empty() &&
630             self.frame_ops.is_empty() &&
631             self.resource_updates.is_empty() &&
632             self.notifications.is_empty()
633     }
634 }
635 
636 /// Creates an image resource with provided parameters.
637 ///
638 /// Must be matched with a `DeleteImage` at some point to prevent memory leaks.
639 #[derive(Clone)]
640 #[cfg_attr(any(feature = "serde"), derive(Deserialize, Serialize))]
641 pub struct AddImage {
642     /// A key to identify the image resource.
643     pub key: ImageKey,
644     /// Properties of the image.
645     pub descriptor: ImageDescriptor,
646     /// The pixels of the image.
647     pub data: ImageData,
648     /// An optional tiling scheme to apply when storing the image's data
649     /// on the GPU. Applies to both width and heights of the tiles.
650     ///
651     /// Note that WebRender may internally chose to tile large images
652     /// even if this member is set to `None`.
653     pub tiling: Option<TileSize>,
654 }
655 
656 /// Updates an already existing image resource.
657 #[derive(Clone)]
658 #[cfg_attr(any(feature = "serde"), derive(Deserialize, Serialize))]
659 pub struct UpdateImage {
660     /// The key identfying the image resource to update.
661     pub key: ImageKey,
662     /// Properties of the image.
663     pub descriptor: ImageDescriptor,
664     /// The pixels of the image.
665     pub data: ImageData,
666     /// An optional dirty rect that lets WebRender optimize the amount of
667     /// data to transfer to the GPU.
668     ///
669     /// The data provided must still represent the entire image.
670     pub dirty_rect: ImageDirtyRect,
671 }
672 
673 /// Creates a blob-image resource with provided parameters.
674 ///
675 /// Must be matched with a `DeleteImage` at some point to prevent memory leaks.
676 #[derive(Clone)]
677 #[cfg_attr(any(feature = "serde"), derive(Deserialize, Serialize))]
678 pub struct AddBlobImage {
679     /// A key to identify the blob-image resource.
680     pub key: BlobImageKey,
681     /// Properties of the image.
682     pub descriptor: ImageDescriptor,
683     /// The blob-image's serialized commands.
684     pub data: Arc<BlobImageData>,
685     /// The portion of the plane in the blob-image's internal coordinate
686     /// system that is stretched to fill the image display item.
687     ///
688     /// Unlike regular images, blob images are not limited in size. The
689     /// top-left corner of their internal coordinate system is also not
690     /// necessary at (0, 0).
691     /// This means that blob images can be updated to insert/remove content
692     /// in any direction to support panning and zooming.
693     pub visible_rect: DeviceIntRect,
694     /// The blob image's tile size to apply when rasterizing the blob-image
695     /// and when storing its rasterized data on the GPU.
696     /// Applies to both width and heights of the tiles.
697     ///
698     /// All blob images are tiled.
699     pub tile_size: TileSize,
700 }
701 
702 /// Updates an already existing blob-image resource.
703 #[derive(Clone)]
704 #[cfg_attr(any(feature = "serde"), derive(Deserialize, Serialize))]
705 pub struct UpdateBlobImage {
706     /// The key identfying the blob-image resource to update.
707     pub key: BlobImageKey,
708     /// Properties of the image.
709     pub descriptor: ImageDescriptor,
710     /// The blob-image's serialized commands.
711     pub data: Arc<BlobImageData>,
712     /// See `AddBlobImage::visible_rect`.
713     pub visible_rect: DeviceIntRect,
714     /// An optional dirty rect that lets WebRender optimize the amount of
715     /// data to to rasterize and transfer to the GPU.
716     pub dirty_rect: BlobDirtyRect,
717 }
718 
719 /// Creates a font resource.
720 ///
721 /// Must be matched with a corresponding `ResourceUpdate::DeleteFont` at some point to prevent
722 /// memory leaks.
723 #[derive(Clone)]
724 #[cfg_attr(any(feature = "serde"), derive(Deserialize, Serialize))]
725 pub enum AddFont {
726     ///
727     Raw(FontKey, Arc<Vec<u8>>, u32),
728     ///
729     Native(FontKey, NativeFontHandle),
730 }
731 
732 /// Creates a font instance resource.
733 ///
734 /// Must be matched with a corresponding `DeleteFontInstance` at some point
735 /// to prevent memory leaks.
736 #[derive(Clone)]
737 #[cfg_attr(any(feature = "serde"), derive(Deserialize, Serialize))]
738 pub struct AddFontInstance {
739     /// A key to identify the font instance.
740     pub key: FontInstanceKey,
741     /// The font resource's key.
742     pub font_key: FontKey,
743     /// Glyph size in app units.
744     pub glyph_size: f32,
745     ///
746     pub options: Option<FontInstanceOptions>,
747     ///
748     pub platform_options: Option<FontInstancePlatformOptions>,
749     ///
750     pub variations: Vec<FontVariation>,
751 }
752 
753 /// Frame messages affect building the scene.
754 pub enum SceneMsg {
755     ///
756     UpdateEpoch(PipelineId, Epoch),
757     ///
758     SetRootPipeline(PipelineId),
759     ///
760     RemovePipeline(PipelineId),
761     ///
762     SetDisplayList {
763         ///
764         display_list: BuiltDisplayList,
765         ///
766         epoch: Epoch,
767         ///
768         pipeline_id: PipelineId,
769         ///
770         background: Option<ColorF>,
771         ///
772         viewport_size: LayoutSize,
773         ///
774         preserve_frame_state: bool,
775     },
776     ///
777     SetDocumentView {
778         ///
779         device_rect: DeviceIntRect,
780     },
781     /// Set the current quality / performance configuration for this document.
782     SetQualitySettings {
783         /// The set of available quality / performance config values.
784         settings: QualitySettings,
785     },
786 }
787 
788 /// Frame messages affect frame generation (applied after building the scene).
789 pub enum FrameMsg {
790     ///
791     UpdateEpoch(PipelineId, Epoch),
792     ///
793     HitTest(Option<PipelineId>, WorldPoint, Sender<HitTestResult>),
794     ///
795     RequestHitTester(Sender<Arc<dyn ApiHitTester>>),
796     ///
797     ScrollNodeWithId(LayoutPoint, ExternalScrollId, ScrollClamping),
798     ///
799     GetScrollNodeState(Sender<Vec<ScrollNodeState>>),
800     ///
801     UpdateDynamicProperties(DynamicProperties),
802     ///
803     AppendDynamicTransformProperties(Vec<PropertyValue<LayoutTransform>>),
804     ///
805     SetIsTransformAsyncZooming(bool, PropertyBindingId),
806 }
807 
808 impl fmt::Debug for SceneMsg {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result809     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
810         f.write_str(match *self {
811             SceneMsg::UpdateEpoch(..) => "SceneMsg::UpdateEpoch",
812             SceneMsg::SetDisplayList { .. } => "SceneMsg::SetDisplayList",
813             SceneMsg::RemovePipeline(..) => "SceneMsg::RemovePipeline",
814             SceneMsg::SetDocumentView { .. } => "SceneMsg::SetDocumentView",
815             SceneMsg::SetRootPipeline(..) => "SceneMsg::SetRootPipeline",
816             SceneMsg::SetQualitySettings { .. } => "SceneMsg::SetQualitySettings",
817         })
818     }
819 }
820 
821 impl fmt::Debug for FrameMsg {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result822     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
823         f.write_str(match *self {
824             FrameMsg::UpdateEpoch(..) => "FrameMsg::UpdateEpoch",
825             FrameMsg::HitTest(..) => "FrameMsg::HitTest",
826             FrameMsg::RequestHitTester(..) => "FrameMsg::RequestHitTester",
827             FrameMsg::ScrollNodeWithId(..) => "FrameMsg::ScrollNodeWithId",
828             FrameMsg::GetScrollNodeState(..) => "FrameMsg::GetScrollNodeState",
829             FrameMsg::UpdateDynamicProperties(..) => "FrameMsg::UpdateDynamicProperties",
830             FrameMsg::AppendDynamicTransformProperties(..) => "FrameMsg::AppendDynamicTransformProperties",
831             FrameMsg::SetIsTransformAsyncZooming(..) => "FrameMsg::SetIsTransformAsyncZooming",
832         })
833     }
834 }
835 
836 bitflags!{
837     /// Bit flags for WR stages to store in a capture.
838     // Note: capturing `FRAME` without `SCENE` is not currently supported.
839     pub struct CaptureBits: u8 {
840         ///
841         const SCENE = 0x1;
842         ///
843         const FRAME = 0x2;
844         ///
845         const TILE_CACHE = 0x4;
846         ///
847         const EXTERNAL_RESOURCES = 0x8;
848     }
849 }
850 
851 bitflags!{
852     /// Mask for clearing caches in debug commands.
853     pub struct ClearCache: u8 {
854         ///
855         const IMAGES = 0b1;
856         ///
857         const GLYPHS = 0b10;
858         ///
859         const GLYPH_DIMENSIONS = 0b100;
860         ///
861         const RENDER_TASKS = 0b1000;
862         ///
863         const TEXTURE_CACHE = 0b10000;
864         /// Clear render target pool
865         const RENDER_TARGETS = 0b100000;
866     }
867 }
868 
869 /// Information about a loaded capture of each document
870 /// that is returned by `RenderBackend`.
871 #[derive(Clone, Debug)]
872 pub struct CapturedDocument {
873     ///
874     pub document_id: DocumentId,
875     ///
876     pub root_pipeline_id: Option<PipelineId>,
877 }
878 
879 /// Update of the state of built-in debugging facilities.
880 #[derive(Clone)]
881 pub enum DebugCommand {
882     /// Sets the provided debug flags.
883     SetFlags(DebugFlags),
884     /// Configure if dual-source blending is used, if available.
885     EnableDualSourceBlending(bool),
886     /// Save a capture of all the documents state.
887     SaveCapture(PathBuf, CaptureBits),
888     /// Load a capture of all the documents state.
889     LoadCapture(PathBuf, Option<(u32, u32)>, Sender<CapturedDocument>),
890     /// Start capturing a sequence of scene/frame changes.
891     StartCaptureSequence(PathBuf, CaptureBits),
892     /// Stop capturing a sequence of scene/frame changes.
893     StopCaptureSequence,
894     /// Clear cached resources, forcing them to be re-uploaded from templates.
895     ClearCaches(ClearCache),
896     /// Enable/disable native compositor usage
897     EnableNativeCompositor(bool),
898     /// Enable/disable parallel job execution with rayon.
899     EnableMultithreading(bool),
900     /// Sets the maximum amount of existing batches to visit before creating a new one.
901     SetBatchingLookback(u32),
902     /// Invalidate GPU cache, forcing the update from the CPU mirror.
903     InvalidateGpuCache,
904     /// Causes the scene builder to pause for a given amount of milliseconds each time it
905     /// processes a transaction.
906     SimulateLongSceneBuild(u32),
907     /// Set an override tile size to use for picture caches
908     SetPictureTileSize(Option<DeviceIntSize>),
909 }
910 
911 /// Message sent by the `RenderApi` to the render backend thread.
912 pub enum ApiMsg {
913     /// Adds a new document namespace.
914     CloneApi(Sender<IdNamespace>),
915     /// Adds a new document namespace.
916     CloneApiByClient(IdNamespace),
917     /// Adds a new document with given initial size.
918     AddDocument(DocumentId, DeviceIntSize),
919     /// A message targeted at a particular document.
920     UpdateDocuments(Vec<Box<TransactionMsg>>),
921     /// Flush from the caches anything that isn't necessary, to free some memory.
922     MemoryPressure,
923     /// Collects a memory report.
924     ReportMemory(Sender<Box<MemoryReport>>),
925     /// Change debugging options.
926     DebugCommand(DebugCommand),
927     /// Message from the scene builder thread.
928     SceneBuilderResult(SceneBuilderResult),
929 }
930 
931 impl fmt::Debug for ApiMsg {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result932     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
933         f.write_str(match *self {
934             ApiMsg::CloneApi(..) => "ApiMsg::CloneApi",
935             ApiMsg::CloneApiByClient(..) => "ApiMsg::CloneApiByClient",
936             ApiMsg::AddDocument(..) => "ApiMsg::AddDocument",
937             ApiMsg::UpdateDocuments(..) => "ApiMsg::UpdateDocuments",
938             ApiMsg::MemoryPressure => "ApiMsg::MemoryPressure",
939             ApiMsg::ReportMemory(..) => "ApiMsg::ReportMemory",
940             ApiMsg::DebugCommand(..) => "ApiMsg::DebugCommand",
941             ApiMsg::SceneBuilderResult(..) => "ApiMsg::SceneBuilderResult",
942         })
943     }
944 }
945 
946 /// Allows the API to communicate with WebRender.
947 ///
948 /// This object is created along with the `Renderer` and it's main use from a
949 /// user perspective is to create one or several `RenderApi` objects.
950 pub struct RenderApiSender {
951     api_sender: Sender<ApiMsg>,
952     scene_sender: Sender<SceneBuilderRequest>,
953     low_priority_scene_sender: Sender<SceneBuilderRequest>,
954     blob_image_handler: Option<Box<dyn BlobImageHandler>>,
955     shared_font_instances: SharedFontInstanceMap,
956 }
957 
958 impl RenderApiSender {
959     /// Used internally by the `Renderer`.
new( api_sender: Sender<ApiMsg>, scene_sender: Sender<SceneBuilderRequest>, low_priority_scene_sender: Sender<SceneBuilderRequest>, blob_image_handler: Option<Box<dyn BlobImageHandler>>, shared_font_instances: SharedFontInstanceMap, ) -> Self960     pub fn new(
961         api_sender: Sender<ApiMsg>,
962         scene_sender: Sender<SceneBuilderRequest>,
963         low_priority_scene_sender: Sender<SceneBuilderRequest>,
964         blob_image_handler: Option<Box<dyn BlobImageHandler>>,
965         shared_font_instances: SharedFontInstanceMap,
966     ) -> Self {
967         RenderApiSender {
968             api_sender,
969             scene_sender,
970             low_priority_scene_sender,
971             blob_image_handler,
972             shared_font_instances,
973         }
974     }
975 
976     /// Creates a new resource API object with a dedicated namespace.
create_api(&self) -> RenderApi977     pub fn create_api(&self) -> RenderApi {
978         let (sync_tx, sync_rx) = single_msg_channel();
979         let msg = ApiMsg::CloneApi(sync_tx);
980         self.api_sender.send(msg).expect("Failed to send CloneApi message");
981         let namespace_id = sync_rx.recv().expect("Failed to receive CloneApi reply");
982         RenderApi {
983             api_sender: self.api_sender.clone(),
984             scene_sender: self.scene_sender.clone(),
985             low_priority_scene_sender: self.low_priority_scene_sender.clone(),
986             namespace_id,
987             next_id: Cell::new(ResourceId(0)),
988             resources: ApiResources::new(
989                 self.blob_image_handler.as_ref().map(|handler| handler.create_similar()),
990                 self.shared_font_instances.clone(),
991             ),
992         }
993     }
994 
995     /// Creates a new resource API object with a dedicated namespace.
996     /// Namespace id is allocated by client.
997     ///
998     /// The function could be used only when RendererOptions::namespace_alloc_by_client is true.
999     /// When the option is true, create_api() could not be used to prevent namespace id conflict.
create_api_by_client(&self, namespace_id: IdNamespace) -> RenderApi1000     pub fn create_api_by_client(&self, namespace_id: IdNamespace) -> RenderApi {
1001         let msg = ApiMsg::CloneApiByClient(namespace_id);
1002         self.api_sender.send(msg).expect("Failed to send CloneApiByClient message");
1003         RenderApi {
1004             api_sender: self.api_sender.clone(),
1005             scene_sender: self.scene_sender.clone(),
1006             low_priority_scene_sender: self.low_priority_scene_sender.clone(),
1007             namespace_id,
1008             next_id: Cell::new(ResourceId(0)),
1009             resources: ApiResources::new(
1010                 self.blob_image_handler.as_ref().map(|handler| handler.create_similar()),
1011                 self.shared_font_instances.clone(),
1012             ),
1013         }
1014     }
1015 }
1016 
1017 /// The main entry point to interact with WebRender.
1018 pub struct RenderApi {
1019     api_sender: Sender<ApiMsg>,
1020     scene_sender: Sender<SceneBuilderRequest>,
1021     low_priority_scene_sender: Sender<SceneBuilderRequest>,
1022     namespace_id: IdNamespace,
1023     next_id: Cell<ResourceId>,
1024     resources: ApiResources,
1025 }
1026 
1027 impl RenderApi {
1028     /// Returns the namespace ID used by this API object.
get_namespace_id(&self) -> IdNamespace1029     pub fn get_namespace_id(&self) -> IdNamespace {
1030         self.namespace_id
1031     }
1032 
1033     ///
create_sender(&self) -> RenderApiSender1034     pub fn create_sender(&self) -> RenderApiSender {
1035         RenderApiSender::new(
1036             self.api_sender.clone(),
1037             self.scene_sender.clone(),
1038             self.low_priority_scene_sender.clone(),
1039             self.resources.blob_image_handler.as_ref().map(|handler| handler.create_similar()),
1040             self.resources.get_shared_font_instances(),
1041         )
1042     }
1043 
1044     /// Add a document to the WebRender instance.
1045     ///
1046     /// Instances can manage one or several documents (using the same render backend thread).
1047     /// Each document will internally correspond to a single scene, and scenes are made of
1048     /// one or several pipelines.
add_document(&self, initial_size: DeviceIntSize) -> DocumentId1049     pub fn add_document(&self, initial_size: DeviceIntSize) -> DocumentId {
1050         let new_id = self.next_unique_id();
1051         self.add_document_with_id(initial_size, new_id)
1052     }
1053 
1054     /// See `add_document`
add_document_with_id(&self, initial_size: DeviceIntSize, id: u32) -> DocumentId1055     pub fn add_document_with_id(&self,
1056                                 initial_size: DeviceIntSize,
1057                                 id: u32) -> DocumentId {
1058         window_size_sanity_check(initial_size);
1059 
1060         let document_id = DocumentId::new(self.namespace_id, id);
1061 
1062         // We send this message to both the render backend and the scene builder instead of having
1063         // the scene builder thread forward it to the render backend as we do elswhere. This is because
1064         // some transactions can skip the scene builder thread and we want to avoid them arriving before
1065         // the render backend knows about the existence of the corresponding document id.
1066         // It may not be necessary, though.
1067         self.api_sender.send(
1068             ApiMsg::AddDocument(document_id, initial_size)
1069         ).unwrap();
1070         self.scene_sender.send(
1071             SceneBuilderRequest::AddDocument(document_id, initial_size)
1072         ).unwrap();
1073 
1074         document_id
1075     }
1076 
1077     /// Delete a document.
delete_document(&self, document_id: DocumentId)1078     pub fn delete_document(&self, document_id: DocumentId) {
1079         self.low_priority_scene_sender.send(
1080             SceneBuilderRequest::DeleteDocument(document_id)
1081         ).unwrap();
1082     }
1083 
1084     /// Generate a new font key
generate_font_key(&self) -> FontKey1085     pub fn generate_font_key(&self) -> FontKey {
1086         let new_id = self.next_unique_id();
1087         FontKey::new(self.namespace_id, new_id)
1088     }
1089 
1090     /// Generate a new font instance key
generate_font_instance_key(&self) -> FontInstanceKey1091     pub fn generate_font_instance_key(&self) -> FontInstanceKey {
1092         let new_id = self.next_unique_id();
1093         FontInstanceKey::new(self.namespace_id, new_id)
1094     }
1095 
1096     /// Gets the dimensions for the supplied glyph keys
1097     ///
1098     /// Note: Internally, the internal texture cache doesn't store
1099     /// 'empty' textures (height or width = 0)
1100     /// This means that glyph dimensions e.g. for spaces (' ') will mostly be None.
get_glyph_dimensions( &self, key: FontInstanceKey, glyph_indices: Vec<GlyphIndex>, ) -> Vec<Option<GlyphDimensions>>1101     pub fn get_glyph_dimensions(
1102         &self,
1103         key: FontInstanceKey,
1104         glyph_indices: Vec<GlyphIndex>,
1105     ) -> Vec<Option<GlyphDimensions>> {
1106         let (sender, rx) = single_msg_channel();
1107         let msg = SceneBuilderRequest::GetGlyphDimensions(GlyphDimensionRequest {
1108             key,
1109             glyph_indices,
1110             sender
1111         });
1112         self.low_priority_scene_sender.send(msg).unwrap();
1113         rx.recv().unwrap()
1114     }
1115 
1116     /// Gets the glyph indices for the supplied string. These
1117     /// can be used to construct GlyphKeys.
get_glyph_indices(&self, key: FontKey, text: &str) -> Vec<Option<u32>>1118     pub fn get_glyph_indices(&self, key: FontKey, text: &str) -> Vec<Option<u32>> {
1119         let (sender, rx) = single_msg_channel();
1120         let msg = SceneBuilderRequest::GetGlyphIndices(GlyphIndexRequest {
1121             key,
1122             text: text.to_string(),
1123             sender,
1124         });
1125         self.low_priority_scene_sender.send(msg).unwrap();
1126         rx.recv().unwrap()
1127     }
1128 
1129     /// Creates an `ImageKey`.
generate_image_key(&self) -> ImageKey1130     pub fn generate_image_key(&self) -> ImageKey {
1131         let new_id = self.next_unique_id();
1132         ImageKey::new(self.namespace_id, new_id)
1133     }
1134 
1135     /// Creates a `BlobImageKey`.
generate_blob_image_key(&self) -> BlobImageKey1136     pub fn generate_blob_image_key(&self) -> BlobImageKey {
1137         BlobImageKey(self.generate_image_key())
1138     }
1139 
1140     /// A Gecko-specific notification mechanism to get some code executed on the
1141     /// `Renderer`'s thread, mostly replaced by `NotificationHandler`. You should
1142     /// probably use the latter instead.
send_external_event(&self, evt: ExternalEvent)1143     pub fn send_external_event(&self, evt: ExternalEvent) {
1144         let msg = SceneBuilderRequest::ExternalEvent(evt);
1145         self.low_priority_scene_sender.send(msg).unwrap();
1146     }
1147 
1148     /// Notify WebRender that now is a good time to flush caches and release
1149     /// as much memory as possible.
notify_memory_pressure(&self)1150     pub fn notify_memory_pressure(&self) {
1151         self.api_sender.send(ApiMsg::MemoryPressure).unwrap();
1152     }
1153 
1154     /// Synchronously requests memory report.
report_memory(&self, _ops: malloc_size_of::MallocSizeOfOps) -> MemoryReport1155     pub fn report_memory(&self, _ops: malloc_size_of::MallocSizeOfOps) -> MemoryReport {
1156         let (tx, rx) = single_msg_channel();
1157         self.api_sender.send(ApiMsg::ReportMemory(tx)).unwrap();
1158         *rx.recv().unwrap()
1159     }
1160 
1161     /// Update debugging flags.
set_debug_flags(&self, flags: DebugFlags)1162     pub fn set_debug_flags(&self, flags: DebugFlags) {
1163         let cmd = DebugCommand::SetFlags(flags);
1164         self.api_sender.send(ApiMsg::DebugCommand(cmd)).unwrap();
1165     }
1166 
1167     /// Stop RenderBackend's task until shut down
stop_render_backend(&self)1168     pub fn stop_render_backend(&self) {
1169         self.low_priority_scene_sender.send(SceneBuilderRequest::StopRenderBackend).unwrap();
1170     }
1171 
1172     /// Shut the WebRender instance down.
shut_down(&self, synchronously: bool)1173     pub fn shut_down(&self, synchronously: bool) {
1174         if synchronously {
1175             let (tx, rx) = single_msg_channel();
1176             self.low_priority_scene_sender.send(SceneBuilderRequest::ShutDown(Some(tx))).unwrap();
1177             rx.recv().unwrap();
1178         } else {
1179             self.low_priority_scene_sender.send(SceneBuilderRequest::ShutDown(None)).unwrap();
1180         }
1181     }
1182 
1183     /// Create a new unique key that can be used for
1184     /// animated property bindings.
generate_property_binding_key<T: Copy>(&self) -> PropertyBindingKey<T>1185     pub fn generate_property_binding_key<T: Copy>(&self) -> PropertyBindingKey<T> {
1186         let new_id = self.next_unique_id();
1187         PropertyBindingKey {
1188             id: PropertyBindingId {
1189                 namespace: self.namespace_id,
1190                 uid: new_id,
1191             },
1192             _phantom: PhantomData,
1193         }
1194     }
1195 
1196     #[inline]
next_unique_id(&self) -> u321197     fn next_unique_id(&self) -> u32 {
1198         let ResourceId(id) = self.next_id.get();
1199         self.next_id.set(ResourceId(id + 1));
1200         id
1201     }
1202 
1203     // For use in Wrench only
1204     #[doc(hidden)]
send_message(&self, msg: ApiMsg)1205     pub fn send_message(&self, msg: ApiMsg) {
1206         self.api_sender.send(msg).unwrap();
1207     }
1208 
1209     /// Creates a transaction message from a single frame message.
frame_message(&self, msg: FrameMsg, document_id: DocumentId) -> Box<TransactionMsg>1210     fn frame_message(&self, msg: FrameMsg, document_id: DocumentId) -> Box<TransactionMsg> {
1211         Box::new(TransactionMsg {
1212             document_id,
1213             scene_ops: Vec::new(),
1214             frame_ops: vec![msg],
1215             resource_updates: Vec::new(),
1216             notifications: Vec::new(),
1217             generate_frame: GenerateFrame::No,
1218             invalidate_rendered_frame: false,
1219             use_scene_builder_thread: false,
1220             low_priority: false,
1221             blob_rasterizer: None,
1222             blob_requests: Vec::new(),
1223             rasterized_blobs: Vec::new(),
1224             profile: TransactionProfile::new(),
1225         })
1226     }
1227 
1228     /// A helper method to send document messages.
send_frame_msg(&self, document_id: DocumentId, msg: FrameMsg)1229     fn send_frame_msg(&self, document_id: DocumentId, msg: FrameMsg) {
1230         // This assertion fails on Servo use-cases, because it creates different
1231         // `RenderApi` instances for layout and compositor.
1232         //assert_eq!(document_id.0, self.namespace_id);
1233         self.api_sender
1234             .send(ApiMsg::UpdateDocuments(vec![self.frame_message(msg, document_id)]))
1235             .unwrap()
1236     }
1237 
1238     /// Send a transaction to WebRender.
send_transaction(&mut self, document_id: DocumentId, transaction: Transaction)1239     pub fn send_transaction(&mut self, document_id: DocumentId, transaction: Transaction) {
1240         let mut transaction = transaction.finalize(document_id);
1241 
1242         self.resources.update(&mut transaction);
1243 
1244         if transaction.generate_frame.as_bool() {
1245             transaction.profile.start_time(profiler::API_SEND_TIME);
1246             transaction.profile.start_time(profiler::TOTAL_FRAME_CPU_TIME);
1247         }
1248 
1249         if transaction.use_scene_builder_thread {
1250             let sender = if transaction.low_priority {
1251                 &mut self.low_priority_scene_sender
1252             } else {
1253                 &mut self.scene_sender
1254             };
1255 
1256             sender.send(SceneBuilderRequest::Transactions(vec![transaction])).unwrap();
1257         } else {
1258             self.api_sender.send(ApiMsg::UpdateDocuments(vec![transaction])).unwrap();
1259         }
1260     }
1261 
1262     /// Does a hit test on display items in the specified document, at the given
1263     /// point. If a pipeline_id is specified, it is used to further restrict the
1264     /// hit results so that only items inside that pipeline are matched. The vector
1265     /// of hit results will contain all display items that match, ordered from
1266     /// front to back.
hit_test(&self, document_id: DocumentId, pipeline_id: Option<PipelineId>, point: WorldPoint, ) -> HitTestResult1267     pub fn hit_test(&self,
1268         document_id: DocumentId,
1269         pipeline_id: Option<PipelineId>,
1270         point: WorldPoint,
1271     ) -> HitTestResult {
1272         let (tx, rx) = single_msg_channel();
1273 
1274         self.send_frame_msg(
1275             document_id,
1276             FrameMsg::HitTest(pipeline_id, point, tx)
1277         );
1278         rx.recv().unwrap()
1279     }
1280 
1281     /// Synchronously request an object that can perform fast hit testing queries.
request_hit_tester(&self, document_id: DocumentId) -> HitTesterRequest1282     pub fn request_hit_tester(&self, document_id: DocumentId) -> HitTesterRequest {
1283         let (tx, rx) = single_msg_channel();
1284         self.send_frame_msg(
1285             document_id,
1286             FrameMsg::RequestHitTester(tx)
1287         );
1288 
1289         HitTesterRequest { rx }
1290     }
1291 
1292     ///
get_scroll_node_state(&self, document_id: DocumentId) -> Vec<ScrollNodeState>1293     pub fn get_scroll_node_state(&self, document_id: DocumentId) -> Vec<ScrollNodeState> {
1294         let (tx, rx) = single_msg_channel();
1295         self.send_frame_msg(document_id, FrameMsg::GetScrollNodeState(tx));
1296         rx.recv().unwrap()
1297     }
1298 
1299     // Some internal scheduling magic that leaked into the API.
1300     // Buckle up and see APZUpdater.cpp for more info about what this is about.
1301     #[doc(hidden)]
wake_scene_builder(&self)1302     pub fn wake_scene_builder(&self) {
1303         self.scene_sender.send(SceneBuilderRequest::WakeUp).unwrap();
1304     }
1305 
1306     /// Block until a round-trip to the scene builder thread has completed. This
1307     /// ensures that any transactions (including ones deferred to the scene
1308     /// builder thread) have been processed.
flush_scene_builder(&self)1309     pub fn flush_scene_builder(&self) {
1310         let (tx, rx) = single_msg_channel();
1311         self.low_priority_scene_sender.send(SceneBuilderRequest::Flush(tx)).unwrap();
1312         rx.recv().unwrap(); // Block until done.
1313     }
1314 
1315     /// Save a capture of the current frame state for debugging.
save_capture(&self, path: PathBuf, bits: CaptureBits)1316     pub fn save_capture(&self, path: PathBuf, bits: CaptureBits) {
1317         let msg = ApiMsg::DebugCommand(DebugCommand::SaveCapture(path, bits));
1318         self.send_message(msg);
1319     }
1320 
1321     /// Load a capture of the current frame state for debugging.
load_capture(&self, path: PathBuf, ids: Option<(u32, u32)>) -> Vec<CapturedDocument>1322     pub fn load_capture(&self, path: PathBuf, ids: Option<(u32, u32)>) -> Vec<CapturedDocument> {
1323         // First flush the scene builder otherwise async scenes might clobber
1324         // the capture we are about to load.
1325         self.flush_scene_builder();
1326 
1327         let (tx, rx) = unbounded_channel();
1328         let msg = ApiMsg::DebugCommand(DebugCommand::LoadCapture(path, ids, tx));
1329         self.send_message(msg);
1330 
1331         let mut documents = Vec::new();
1332         while let Ok(captured_doc) = rx.recv() {
1333             documents.push(captured_doc);
1334         }
1335         documents
1336     }
1337 
1338     /// Start capturing a sequence of frames.
start_capture_sequence(&self, path: PathBuf, bits: CaptureBits)1339     pub fn start_capture_sequence(&self, path: PathBuf, bits: CaptureBits) {
1340         let msg = ApiMsg::DebugCommand(DebugCommand::StartCaptureSequence(path, bits));
1341         self.send_message(msg);
1342     }
1343 
1344     /// Stop capturing sequences of frames.
stop_capture_sequence(&self)1345     pub fn stop_capture_sequence(&self) {
1346         let msg = ApiMsg::DebugCommand(DebugCommand::StopCaptureSequence);
1347         self.send_message(msg);
1348     }
1349 
1350     /// Update the state of builtin debugging facilities.
send_debug_cmd(&mut self, cmd: DebugCommand)1351     pub fn send_debug_cmd(&mut self, cmd: DebugCommand) {
1352         if let DebugCommand::EnableMultithreading(enable) = cmd {
1353             // TODO(nical) we should enable it for all RenderApis.
1354             self.resources.enable_multithreading(enable);
1355         }
1356         let msg = ApiMsg::DebugCommand(cmd);
1357         self.send_message(msg);
1358     }
1359 }
1360 
1361 impl Drop for RenderApi {
drop(&mut self)1362     fn drop(&mut self) {
1363         let msg = SceneBuilderRequest::ClearNamespace(self.namespace_id);
1364         let _ = self.low_priority_scene_sender.send(msg);
1365     }
1366 }
1367 
1368 
window_size_sanity_check(size: DeviceIntSize)1369 fn window_size_sanity_check(size: DeviceIntSize) {
1370     // Anything bigger than this will crash later when attempting to create
1371     // a render task.
1372     use crate::render_task::MAX_RENDER_TASK_SIZE;
1373     if size.width > MAX_RENDER_TASK_SIZE || size.height > MAX_RENDER_TASK_SIZE {
1374         panic!("Attempting to create a {}x{} window/document", size.width, size.height);
1375     }
1376 }
1377 
1378 /// Collection of heap sizes, in bytes.
1379 /// cbindgen:derive-eq=false
1380 /// cbindgen:derive-ostream=false
1381 #[repr(C)]
1382 #[allow(missing_docs)]
1383 #[derive(AddAssign, Clone, Debug, Default)]
1384 pub struct MemoryReport {
1385     //
1386     // CPU Memory.
1387     //
1388     pub clip_stores: usize,
1389     pub gpu_cache_metadata: usize,
1390     pub gpu_cache_cpu_mirror: usize,
1391     pub render_tasks: usize,
1392     pub hit_testers: usize,
1393     pub fonts: usize,
1394     pub weak_fonts: usize,
1395     pub images: usize,
1396     pub rasterized_blobs: usize,
1397     pub shader_cache: usize,
1398     pub interning: InterningMemoryReport,
1399     pub display_list: usize,
1400     pub upload_staging_memory: usize,
1401     pub swgl: usize,
1402 
1403     //
1404     // GPU memory.
1405     //
1406     pub gpu_cache_textures: usize,
1407     pub vertex_data_textures: usize,
1408     pub render_target_textures: usize,
1409     pub picture_tile_textures: usize,
1410     pub atlas_textures: usize,
1411     pub standalone_textures: usize,
1412     pub texture_cache_structures: usize,
1413     pub depth_target_textures: usize,
1414     pub texture_upload_pbos: usize,
1415     pub swap_chain: usize,
1416     pub render_texture_hosts: usize,
1417     pub upload_staging_textures: usize,
1418 }
1419