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