tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

render_api.rs (56615B)


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