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