webrender/
render_api.rs

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