webrender_api/
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
7extern crate serde_bytes;
8
9use crate::channel::{self, MsgSender, Payload, PayloadSender, PayloadSenderHelperMethods};
10use peek_poke::PeekPoke;
11use std::cell::Cell;
12use std::fmt;
13use std::marker::PhantomData;
14use std::os::raw::c_void;
15use std::path::PathBuf;
16use std::sync::Arc;
17use std::u32;
18// local imports
19use crate::{display_item as di, font};
20use crate::color::{ColorU, ColorF};
21use crate::display_list::{BuiltDisplayList, BuiltDisplayListDescriptor};
22use crate::image::{BlobImageData, BlobImageKey, ImageData, ImageDescriptor, ImageKey};
23use crate::units::*;
24
25/// Width and height in device pixels of image tiles.
26pub type TileSize = u16;
27
28/// Documents are rendered in the ascending order of their associated layer values.
29pub type DocumentLayer = i8;
30
31/// Various settings that the caller can select based on desired tradeoffs
32/// between rendering quality and performance / power usage.
33#[derive(Copy, Clone, Deserialize, Serialize)]
34pub struct QualitySettings {
35    /// If true, allow picture cache slices to be created that may prevent
36    /// subpixel AA on text being used due to lack of opaque background. This
37    /// often allows a significant performance win on pages that interleave
38    /// scroll regions with fixed position elements.
39    pub allow_sacrificing_subpixel_aa: bool,
40}
41
42impl Default for QualitySettings {
43    fn default() -> Self {
44        QualitySettings {
45            // Preferring performance in this case retains the current behavior.
46            allow_sacrificing_subpixel_aa: true,
47        }
48    }
49}
50
51/// Update of a persistent resource in WebRender.
52///
53/// ResourceUpdate changes keep theirs effect across display list changes.
54#[derive(Clone, Deserialize, Serialize)]
55pub enum ResourceUpdate {
56    /// See `AddImage`.
57    AddImage(AddImage),
58    /// See `UpdateImage`.
59    UpdateImage(UpdateImage),
60    /// See `AddBlobImage`.
61    AddBlobImage(AddBlobImage),
62    /// See `UpdateBlobImage`.
63    UpdateBlobImage(UpdateBlobImage),
64    /// Delete an existing image or blob-image resource.
65    ///
66    /// It is invalid to continue referring to the image key in any display list
67    /// in the transaction that contains the `DeleteImage` message and subsequent
68    /// transactions.
69    DeleteImage(ImageKey),
70    /// See `AddBlobImage::visible_area`.
71    SetBlobImageVisibleArea(BlobImageKey, DeviceIntRect),
72    /// See `AddFont`.
73    AddFont(AddFont),
74    /// Deletes an already existing font resource.
75    ///
76    /// It is invalid to continue referring to the font key in any display list
77    /// in the transaction that contains the `DeleteImage` message and subsequent
78    /// transactions.
79    DeleteFont(font::FontKey),
80    /// See `AddFontInstance`.
81    AddFontInstance(AddFontInstance),
82    /// Deletes an already existing font instance resource.
83    ///
84    /// It is invalid to continue referring to the font instance in any display
85    /// list in the transaction that contains the `DeleteImage` message and
86    /// subsequent transactions.
87    DeleteFontInstance(font::FontInstanceKey),
88}
89
90impl fmt::Debug for ResourceUpdate {
91    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
92        match self {
93            ResourceUpdate::AddImage(ref i) => f.write_fmt(format_args!(
94                "ResourceUpdate::AddImage size({:?})",
95                &i.descriptor.size
96            )),
97            ResourceUpdate::UpdateImage(ref i) => f.write_fmt(format_args!(
98                "ResourceUpdate::UpdateImage size({:?})",
99                &i.descriptor.size
100            )),
101            ResourceUpdate::AddBlobImage(ref i) => f.write_fmt(format_args!(
102                "ResourceUpdate::AddBlobImage size({:?})",
103                &i.descriptor.size
104            )),
105            ResourceUpdate::UpdateBlobImage(i) => f.write_fmt(format_args!(
106                "ResourceUpdate::UpdateBlobImage size({:?})",
107                &i.descriptor.size
108            )),
109            ResourceUpdate::DeleteImage(..) => f.write_str("ResourceUpdate::DeleteImage"),
110            ResourceUpdate::SetBlobImageVisibleArea(..) => f.write_str("ResourceUpdate::SetBlobImageVisibleArea"),
111            ResourceUpdate::AddFont(..) => f.write_str("ResourceUpdate::AddFont"),
112            ResourceUpdate::DeleteFont(..) => f.write_str("ResourceUpdate::DeleteFont"),
113            ResourceUpdate::AddFontInstance(..) => f.write_str("ResourceUpdate::AddFontInstance"),
114            ResourceUpdate::DeleteFontInstance(..) => f.write_str("ResourceUpdate::DeleteFontInstance"),
115        }
116    }
117}
118
119/// A Transaction is a group of commands to apply atomically to a document.
120///
121/// This mechanism ensures that:
122///  - no other message can be interleaved between two commands that need to be applied together.
123///  - no redundant work is performed if two commands in the same transaction cause the scene or
124///    the frame to be rebuilt.
125pub struct Transaction {
126    /// Operations affecting the scene (applied before scene building).
127    scene_ops: Vec<SceneMsg>,
128    /// Operations affecting the generation of frames (applied after scene building).
129    frame_ops: Vec<FrameMsg>,
130
131    /// Additional display list data.
132    payloads: Vec<Payload>,
133
134    notifications: Vec<NotificationRequest>,
135
136    /// Persistent resource updates to apply as part of this transaction.
137    pub resource_updates: Vec<ResourceUpdate>,
138
139    /// If true the transaction is piped through the scene building thread, if false
140    /// it will be applied directly on the render backend.
141    use_scene_builder_thread: bool,
142
143    generate_frame: bool,
144
145    /// Set to true in order to force re-rendering even if WebRender can't internally
146    /// detect that something has changed.
147    pub invalidate_rendered_frame: bool,
148
149    low_priority: bool,
150}
151
152impl Transaction {
153    /// Constructor.
154    pub fn new() -> Self {
155        Transaction {
156            scene_ops: Vec::new(),
157            frame_ops: Vec::new(),
158            resource_updates: Vec::new(),
159            payloads: Vec::new(),
160            notifications: Vec::new(),
161            use_scene_builder_thread: true,
162            generate_frame: false,
163            invalidate_rendered_frame: false,
164            low_priority: false,
165        }
166    }
167
168    /// Marks this transaction to allow it to skip going through the scene builder
169    /// thread.
170    ///
171    /// This is useful to avoid jank in transaction associated with animated
172    /// property updates, panning and zooming.
173    ///
174    /// Note that transactions that skip the scene builder thread can race ahead of
175    /// transactions that don't skip it.
176    pub fn skip_scene_builder(&mut self) {
177        self.use_scene_builder_thread = false;
178    }
179
180    /// Marks this transaction to enforce going through the scene builder thread.
181    pub fn use_scene_builder_thread(&mut self) {
182        self.use_scene_builder_thread = true;
183    }
184
185    /// Returns true if the transaction has no effect.
186    pub fn is_empty(&self) -> bool {
187        !self.generate_frame &&
188            !self.invalidate_rendered_frame &&
189            self.scene_ops.is_empty() &&
190            self.frame_ops.is_empty() &&
191            self.resource_updates.is_empty() &&
192            self.notifications.is_empty()
193    }
194
195    /// Update a pipeline's epoch.
196    pub fn update_epoch(&mut self, pipeline_id: PipelineId, epoch: Epoch) {
197        // We track epochs before and after scene building.
198        // This one will be applied to the pending scene right away:
199        self.scene_ops.push(SceneMsg::UpdateEpoch(pipeline_id, epoch));
200        // And this one will be applied to the currently built scene at the end
201        // of the transaction (potentially long after the scene_ops one).
202        self.frame_ops.push(FrameMsg::UpdateEpoch(pipeline_id, epoch));
203        // We could avoid the duplication here by storing the epoch updates in a
204        // separate array and let the render backend schedule the updates at the
205        // proper times, but it wouldn't make things simpler.
206    }
207
208    /// Sets the root pipeline.
209    ///
210    /// # Examples
211    ///
212    /// ```
213    /// # use webrender_api::{PipelineId, RenderApiSender, Transaction};
214    /// # use webrender_api::units::{DeviceIntSize};
215    /// # fn example() {
216    /// let pipeline_id = PipelineId(0, 0);
217    /// let mut txn = Transaction::new();
218    /// txn.set_root_pipeline(pipeline_id);
219    /// # }
220    /// ```
221    pub fn set_root_pipeline(&mut self, pipeline_id: PipelineId) {
222        self.scene_ops.push(SceneMsg::SetRootPipeline(pipeline_id));
223    }
224
225    /// Removes data associated with a pipeline from the internal data structures.
226    /// If the specified `pipeline_id` is for the root pipeline, the root pipeline
227    /// is reset back to `None`.
228    pub fn remove_pipeline(&mut self, pipeline_id: PipelineId) {
229        self.scene_ops.push(SceneMsg::RemovePipeline(pipeline_id));
230    }
231
232    /// Supplies a new frame to WebRender.
233    ///
234    /// Non-blocking, it notifies a worker process which processes the display list.
235    ///
236    /// Note: Scrolling doesn't require an own Frame.
237    ///
238    /// Arguments:
239    ///
240    /// * `epoch`: The unique Frame ID, monotonically increasing.
241    /// * `background`: The background color of this pipeline.
242    /// * `viewport_size`: The size of the viewport for this frame.
243    /// * `pipeline_id`: The ID of the pipeline that is supplying this display list.
244    /// * `content_size`: The total screen space size of this display list's display items.
245    /// * `display_list`: The root Display list used in this frame.
246    /// * `preserve_frame_state`: If a previous frame exists which matches this pipeline
247    ///                           id, this setting determines if frame state (such as scrolling
248    ///                           position) should be preserved for this new display list.
249    pub fn set_display_list(
250        &mut self,
251        epoch: Epoch,
252        background: Option<ColorF>,
253        viewport_size: LayoutSize,
254        (pipeline_id, content_size, display_list): (PipelineId, LayoutSize, BuiltDisplayList),
255        preserve_frame_state: bool,
256    ) {
257        let (display_list_data, list_descriptor) = display_list.into_data();
258        self.scene_ops.push(
259            SceneMsg::SetDisplayList {
260                epoch,
261                pipeline_id,
262                background,
263                viewport_size,
264                content_size,
265                list_descriptor,
266                preserve_frame_state,
267            }
268        );
269        self.payloads.push(Payload { epoch, pipeline_id, display_list_data });
270    }
271
272    /// Add a set of persistent resource updates to apply as part of this transaction.
273    pub fn update_resources(&mut self, mut resources: Vec<ResourceUpdate>) {
274        self.resource_updates.append(&mut resources);
275    }
276
277    // Note: Gecko uses this to get notified when a transaction that contains
278    // potentially long blob rasterization or scene build is ready to be rendered.
279    // so that the tab-switching integration can react adequately when tab
280    // switching takes too long. For this use case when matters is that the
281    // notification doesn't fire before scene building and blob rasterization.
282
283    /// Trigger a notification at a certain stage of the rendering pipeline.
284    ///
285    /// Not that notification requests are skipped during serialization, so is is
286    /// best to use them for synchronization purposes and not for things that could
287    /// affect the WebRender's state.
288    pub fn notify(&mut self, event: NotificationRequest) {
289        self.notifications.push(event);
290    }
291
292    /// Setup the output region in the framebuffer for a given document.
293    pub fn set_document_view(
294        &mut self,
295        device_rect: DeviceIntRect,
296        device_pixel_ratio: f32,
297    ) {
298        self.scene_ops.push(
299            SceneMsg::SetDocumentView {
300                device_rect,
301                device_pixel_ratio,
302            },
303        );
304    }
305
306    /// Enable copying of the output of this pipeline id to
307    /// an external texture for callers to consume.
308    pub fn enable_frame_output(&mut self, pipeline_id: PipelineId, enable: bool) {
309        self.scene_ops.push(SceneMsg::EnableFrameOutput(pipeline_id, enable));
310    }
311
312    /// Scrolls the scrolling layer under the `cursor`
313    ///
314    /// WebRender looks for the layer closest to the user
315    /// which has `ScrollPolicy::Scrollable` set.
316    pub fn scroll(&mut self, scroll_location: ScrollLocation, cursor: WorldPoint) {
317        self.frame_ops.push(FrameMsg::Scroll(scroll_location, cursor));
318    }
319
320    ///
321    pub fn scroll_node_with_id(
322        &mut self,
323        origin: LayoutPoint,
324        id: di::ExternalScrollId,
325        clamp: ScrollClamping,
326    ) {
327        self.frame_ops.push(FrameMsg::ScrollNodeWithId(origin, id, clamp));
328    }
329
330    /// Set the current quality / performance settings for this document.
331    pub fn set_quality_settings(&mut self, settings: QualitySettings) {
332        self.scene_ops.push(SceneMsg::SetQualitySettings { settings });
333    }
334
335    ///
336    pub fn set_page_zoom(&mut self, page_zoom: ZoomFactor) {
337        self.scene_ops.push(SceneMsg::SetPageZoom(page_zoom));
338    }
339
340    ///
341    pub fn set_pinch_zoom(&mut self, pinch_zoom: ZoomFactor) {
342        self.frame_ops.push(FrameMsg::SetPinchZoom(pinch_zoom));
343    }
344
345    ///
346    pub fn set_is_transform_async_zooming(&mut self, is_zooming: bool, animation_id: PropertyBindingId) {
347        self.frame_ops.push(FrameMsg::SetIsTransformAsyncZooming(is_zooming, animation_id));
348    }
349
350    ///
351    pub fn set_pan(&mut self, pan: DeviceIntPoint) {
352        self.frame_ops.push(FrameMsg::SetPan(pan));
353    }
354
355    /// Generate a new frame. When it's done and a RenderNotifier has been set
356    /// in `webrender::Renderer`, [new_frame_ready()][notifier] gets called.
357    /// Note that the notifier is called even if the frame generation was a
358    /// no-op; the arguments passed to `new_frame_ready` will provide information
359    /// as to when happened.
360    ///
361    /// [notifier]: trait.RenderNotifier.html#tymethod.new_frame_ready
362    pub fn generate_frame(&mut self) {
363        self.generate_frame = true;
364    }
365
366    /// Invalidate rendered frame. It ensure that frame will be rendered during
367    /// next frame generation. WebRender could skip frame rendering if there
368    /// is no update.
369    /// But there are cases that needs to force rendering.
370    ///  - Content of image is updated by reusing same ExternalImageId.
371    ///  - Platform requests it if pixels become stale (like wakeup from standby).
372    pub fn invalidate_rendered_frame(&mut self) {
373        self.invalidate_rendered_frame = true;
374    }
375
376    /// Supply a list of animated property bindings that should be used to resolve
377    /// bindings in the current display list.
378    pub fn update_dynamic_properties(&mut self, properties: DynamicProperties) {
379        self.frame_ops.push(FrameMsg::UpdateDynamicProperties(properties));
380    }
381
382    /// Add to the list of animated property bindings that should be used to
383    /// resolve bindings in the current display list. This is a convenience method
384    /// so the caller doesn't have to figure out all the dynamic properties before
385    /// setting them on the transaction but can do them incrementally.
386    pub fn append_dynamic_properties(&mut self, properties: DynamicProperties) {
387        self.frame_ops.push(FrameMsg::AppendDynamicProperties(properties));
388    }
389
390    /// Consumes this object and just returns the frame ops.
391    pub fn get_frame_ops(self) -> Vec<FrameMsg> {
392        self.frame_ops
393    }
394
395    fn finalize(self) -> (TransactionMsg, Vec<Payload>) {
396        (
397            TransactionMsg {
398                scene_ops: self.scene_ops,
399                frame_ops: self.frame_ops,
400                resource_updates: self.resource_updates,
401                notifications: self.notifications,
402                use_scene_builder_thread: self.use_scene_builder_thread,
403                generate_frame: self.generate_frame,
404                invalidate_rendered_frame: self.invalidate_rendered_frame,
405                low_priority: self.low_priority,
406            },
407            self.payloads,
408        )
409    }
410
411    /// See `ResourceUpdate::AddImage`.
412    pub fn add_image(
413        &mut self,
414        key: ImageKey,
415        descriptor: ImageDescriptor,
416        data: ImageData,
417        tiling: Option<TileSize>,
418    ) {
419        self.resource_updates.push(ResourceUpdate::AddImage(AddImage {
420            key,
421            descriptor,
422            data,
423            tiling,
424        }));
425    }
426
427    /// See `ResourceUpdate::UpdateImage`.
428    pub fn update_image(
429        &mut self,
430        key: ImageKey,
431        descriptor: ImageDescriptor,
432        data: ImageData,
433        dirty_rect: &ImageDirtyRect,
434    ) {
435        self.resource_updates.push(ResourceUpdate::UpdateImage(UpdateImage {
436            key,
437            descriptor,
438            data,
439            dirty_rect: *dirty_rect,
440        }));
441    }
442
443    /// See `ResourceUpdate::DeleteImage`.
444    pub fn delete_image(&mut self, key: ImageKey) {
445        self.resource_updates.push(ResourceUpdate::DeleteImage(key));
446    }
447
448    /// See `ResourceUpdate::AddBlobImage`.
449    pub fn add_blob_image(
450        &mut self,
451        key: BlobImageKey,
452        descriptor: ImageDescriptor,
453        data: Arc<BlobImageData>,
454        visible_rect: DeviceIntRect,
455        tiling: Option<TileSize>,
456    ) {
457        self.resource_updates.push(
458            ResourceUpdate::AddBlobImage(AddBlobImage {
459                key,
460                descriptor,
461                data,
462                visible_rect,
463                tiling,
464            })
465        );
466    }
467
468    /// See `ResourceUpdate::UpdateBlobImage`.
469    pub fn update_blob_image(
470        &mut self,
471        key: BlobImageKey,
472        descriptor: ImageDescriptor,
473        data: Arc<BlobImageData>,
474        visible_rect: DeviceIntRect,
475        dirty_rect: &BlobDirtyRect,
476    ) {
477        self.resource_updates.push(
478            ResourceUpdate::UpdateBlobImage(UpdateBlobImage {
479                key,
480                descriptor,
481                data,
482                visible_rect,
483                dirty_rect: *dirty_rect,
484            })
485        );
486    }
487
488    /// See `ResourceUpdate::DeleteBlobImage`.
489    pub fn delete_blob_image(&mut self, key: BlobImageKey) {
490        self.resource_updates.push(ResourceUpdate::DeleteImage(key.as_image()));
491    }
492
493    /// See `ResourceUpdate::SetBlobImageVisibleArea`.
494    pub fn set_blob_image_visible_area(&mut self, key: BlobImageKey, area: DeviceIntRect) {
495        self.resource_updates.push(ResourceUpdate::SetBlobImageVisibleArea(key, area))
496    }
497
498    /// See `ResourceUpdate::AddFont`.
499    pub fn add_raw_font(&mut self, key: font::FontKey, bytes: Vec<u8>, index: u32) {
500        self.resource_updates
501            .push(ResourceUpdate::AddFont(AddFont::Raw(key, bytes, index)));
502    }
503
504    /// See `ResourceUpdate::AddFont`.
505    pub fn add_native_font(&mut self, key: font::FontKey, native_handle: font::NativeFontHandle) {
506        self.resource_updates
507            .push(ResourceUpdate::AddFont(AddFont::Native(key, native_handle)));
508    }
509
510    /// See `ResourceUpdate::DeleteFont`.
511    pub fn delete_font(&mut self, key: font::FontKey) {
512        self.resource_updates.push(ResourceUpdate::DeleteFont(key));
513    }
514
515    /// See `ResourceUpdate::AddFontInstance`.
516    pub fn add_font_instance(
517        &mut self,
518        key: font::FontInstanceKey,
519        font_key: font::FontKey,
520        glyph_size: Au,
521        options: Option<font::FontInstanceOptions>,
522        platform_options: Option<font::FontInstancePlatformOptions>,
523        variations: Vec<font::FontVariation>,
524    ) {
525        self.resource_updates
526            .push(ResourceUpdate::AddFontInstance(AddFontInstance {
527                key,
528                font_key,
529                glyph_size,
530                options,
531                platform_options,
532                variations,
533            }));
534    }
535
536    /// See `ResourceUpdate::DeleteFontInstance`.
537    pub fn delete_font_instance(&mut self, key: font::FontInstanceKey) {
538        self.resource_updates.push(ResourceUpdate::DeleteFontInstance(key));
539    }
540
541    /// A hint that this transaction can be processed at a lower priority. High-
542    /// priority transactions can jump ahead of regular-priority transactions,
543    /// but both high- and regular-priority transactions are processed in order
544    /// relative to other transactions of the same priority.
545    pub fn set_low_priority(&mut self, low_priority: bool) {
546        self.low_priority = low_priority;
547    }
548
549    /// Returns whether this transaction is marked as low priority.
550    pub fn is_low_priority(&self) -> bool {
551        self.low_priority
552    }
553}
554
555///
556pub struct DocumentTransaction {
557    ///
558    pub document_id: DocumentId,
559    ///
560    pub transaction: Transaction,
561}
562
563/// Represents a transaction in the format sent through the channel.
564#[derive(Clone, Deserialize, Serialize)]
565pub struct TransactionMsg {
566    /// Changes that require re-building the scene.
567    pub scene_ops: Vec<SceneMsg>,
568    /// Changes to animated properties that do not require re-building the scene.
569    pub frame_ops: Vec<FrameMsg>,
570    /// Updates to resources that persist across display lists.
571    pub resource_updates: Vec<ResourceUpdate>,
572    /// Whether to trigger frame building and rendering if something has changed.
573    pub generate_frame: bool,
574    /// Whether to force frame building and rendering even if no changes are internally
575    /// observed.
576    pub invalidate_rendered_frame: bool,
577    /// Whether to enforce that this transaction go through the scene builder.
578    pub use_scene_builder_thread: bool,
579    ///
580    pub low_priority: bool,
581
582    /// Handlers to notify at certain points of the pipeline.
583    #[serde(skip)]
584    pub notifications: Vec<NotificationRequest>,
585}
586
587impl fmt::Debug for TransactionMsg {
588    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
589        writeln!(f, "threaded={}, genframe={}, invalidate={}, low_priority={}",
590                        self.use_scene_builder_thread,
591                        self.generate_frame,
592                        self.invalidate_rendered_frame,
593                        self.low_priority,
594                    ).unwrap();
595        for scene_op in &self.scene_ops {
596            writeln!(f, "\t\t{:?}", scene_op).unwrap();
597        }
598
599        for frame_op in &self.frame_ops {
600            writeln!(f, "\t\t{:?}", frame_op).unwrap();
601        }
602
603        for resource_update in &self.resource_updates {
604            writeln!(f, "\t\t{:?}", resource_update).unwrap();
605        }
606        Ok(())
607    }
608}
609
610impl TransactionMsg {
611    /// Returns true if this transaction has no effect.
612    pub fn is_empty(&self) -> bool {
613        !self.generate_frame &&
614            !self.invalidate_rendered_frame &&
615            self.scene_ops.is_empty() &&
616            self.frame_ops.is_empty() &&
617            self.resource_updates.is_empty() &&
618            self.notifications.is_empty()
619    }
620
621    /// Creates a transaction message from a single frame message.
622    pub fn frame_message(msg: FrameMsg) -> Self {
623        TransactionMsg {
624            scene_ops: Vec::new(),
625            frame_ops: vec![msg],
626            resource_updates: Vec::new(),
627            notifications: Vec::new(),
628            generate_frame: false,
629            invalidate_rendered_frame: false,
630            use_scene_builder_thread: false,
631            low_priority: false,
632        }
633    }
634
635    /// Creates a transaction message from a single scene message.
636    pub fn scene_message(msg: SceneMsg) -> Self {
637        TransactionMsg {
638            scene_ops: vec![msg],
639            frame_ops: Vec::new(),
640            resource_updates: Vec::new(),
641            notifications: Vec::new(),
642            generate_frame: false,
643            invalidate_rendered_frame: false,
644            use_scene_builder_thread: false,
645            low_priority: false,
646        }
647    }
648}
649
650/// Creates an image resource with provided parameters.
651///
652/// Must be matched with a `DeleteImage` at some point to prevent memory leaks.
653#[derive(Clone, Deserialize, Serialize)]
654pub struct AddImage {
655    /// A key to identify the image resource.
656    pub key: ImageKey,
657    /// Properties of the image.
658    pub descriptor: ImageDescriptor,
659    /// The pixels of the image.
660    pub data: ImageData,
661    /// An optional tiling scheme to apply when storing the image's data
662    /// on the GPU. Applies to both width and heights of the tiles.
663    ///
664    /// Note that WebRender may internally chose to tile large images
665    /// even if this member is set to `None`.
666    pub tiling: Option<TileSize>,
667}
668
669/// Updates an already existing image resource.
670#[derive(Clone, Deserialize, Serialize)]
671pub struct UpdateImage {
672    /// The key identfying the image resource to update.
673    pub key: ImageKey,
674    /// Properties of the image.
675    pub descriptor: ImageDescriptor,
676    /// The pixels of the image.
677    pub data: ImageData,
678    /// An optional dirty rect that lets WebRender optimize the amount of
679    /// data to transfer to the GPU.
680    ///
681    /// The data provided must still represent the entire image.
682    pub dirty_rect: ImageDirtyRect,
683}
684
685/// Creates a blob-image resource with provided parameters.
686///
687/// Must be matched with a `DeleteImage` at some point to prevent memory leaks.
688#[derive(Clone, Deserialize, Serialize)]
689pub struct AddBlobImage {
690    /// A key to identify the blob-image resource.
691    pub key: BlobImageKey,
692    /// Properties of the image.
693    pub descriptor: ImageDescriptor,
694    /// The blob-image's serialized commands.
695    pub data: Arc<BlobImageData>,
696    /// The portion of the plane in the blob-image's internal coordinate
697    /// system that is stretched to fill the image display item.
698    ///
699    /// Unlike regular images, blob images are not limited in size. The
700    /// top-left corner of their internal coordinate system is also not
701    /// necessary at (0, 0).
702    /// This means that blob images can be updated to insert/remove content
703    /// in any direction to support panning and zooming.
704    pub visible_rect: DeviceIntRect,
705    /// An optional tiling scheme to apply when rasterizing the blob-image
706    /// and when storing its rasterized data on the GPU.
707    /// Applies to both width and heights of the tiles.
708    ///
709    /// Note that WebRender may internally chose to tile large blob-images
710    /// even if this member is set to `None`.
711    pub tiling: Option<TileSize>,
712}
713
714/// Updates an already existing blob-image resource.
715#[derive(Clone, Deserialize, Serialize)]
716pub struct UpdateBlobImage {
717    /// The key identfying the blob-image resource to update.
718    pub key: BlobImageKey,
719    /// Properties of the image.
720    pub descriptor: ImageDescriptor,
721    /// The blob-image's serialized commands.
722    pub data: Arc<BlobImageData>,
723    /// See `AddBlobImage::visible_rect`.
724    pub visible_rect: DeviceIntRect,
725    /// An optional dirty rect that lets WebRender optimize the amount of
726    /// data to to rasterize and transfer to the GPU.
727    pub dirty_rect: BlobDirtyRect,
728}
729
730/// Creates a font resource.
731///
732/// Must be matched with a corresponding `ResourceUpdate::DeleteFont` at some point to prevent
733/// memory leaks.
734#[derive(Clone, Deserialize, Serialize)]
735pub enum AddFont {
736    ///
737    Raw(
738        font::FontKey,
739        #[serde(with = "serde_bytes")] Vec<u8>,
740        u32
741    ),
742    ///
743    Native(font::FontKey, font::NativeFontHandle),
744}
745
746/// Describe an item that matched a hit-test query.
747#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
748pub struct HitTestItem {
749    /// The pipeline that the display item that was hit belongs to.
750    pub pipeline: PipelineId,
751
752    /// The tag of the hit display item.
753    pub tag: di::ItemTag,
754
755    /// The hit point in the coordinate space of the "viewport" of the display item. The
756    /// viewport is the scroll node formed by the root reference frame of the display item's
757    /// pipeline.
758    pub point_in_viewport: LayoutPoint,
759
760    /// The coordinates of the original hit test point relative to the origin of this item.
761    /// This is useful for calculating things like text offsets in the client.
762    pub point_relative_to_item: LayoutPoint,
763}
764
765/// Returned by `RenderApi::hit_test`.
766#[derive(Clone, Debug, Default, Deserialize, Serialize)]
767pub struct HitTestResult {
768    /// List of items that are match the hit-test query.
769    pub items: Vec<HitTestItem>,
770}
771
772bitflags! {
773    #[derive(Deserialize, MallocSizeOf, Serialize)]
774    ///
775    pub struct HitTestFlags: u8 {
776        ///
777        const FIND_ALL = 0b00000001;
778        ///
779        const POINT_RELATIVE_TO_PIPELINE_VIEWPORT = 0b00000010;
780    }
781}
782
783/// Creates a font instance resource.
784///
785/// Must be matched with a corresponding `DeleteFontInstance` at some point
786/// to prevent memory leaks.
787#[derive(Clone, Deserialize, Serialize)]
788pub struct AddFontInstance {
789    /// A key to identify the font instance.
790    pub key: font::FontInstanceKey,
791    /// The font resource's key.
792    pub font_key: font::FontKey,
793    /// Glyph size in app units.
794    pub glyph_size: Au,
795    ///
796    pub options: Option<font::FontInstanceOptions>,
797    ///
798    pub platform_options: Option<font::FontInstancePlatformOptions>,
799    ///
800    pub variations: Vec<font::FontVariation>,
801}
802
803/// Frame messages affect building the scene.
804#[derive(Clone, Deserialize, Serialize)]
805pub enum SceneMsg {
806    ///
807    UpdateEpoch(PipelineId, Epoch),
808    ///
809    SetPageZoom(ZoomFactor),
810    ///
811    SetRootPipeline(PipelineId),
812    ///
813    RemovePipeline(PipelineId),
814    ///
815    EnableFrameOutput(PipelineId, bool),
816    ///
817    SetDisplayList {
818        ///
819        list_descriptor: BuiltDisplayListDescriptor,
820        ///
821        epoch: Epoch,
822        ///
823        pipeline_id: PipelineId,
824        ///
825        background: Option<ColorF>,
826        ///
827        viewport_size: LayoutSize,
828        ///
829        content_size: LayoutSize,
830        ///
831        preserve_frame_state: bool,
832    },
833    ///
834    SetDocumentView {
835        ///
836        device_rect: DeviceIntRect,
837        ///
838        device_pixel_ratio: f32,
839    },
840    /// Set the current quality / performance configuration for this document.
841    SetQualitySettings {
842        /// The set of available quality / performance config values.
843        settings: QualitySettings,
844    },
845}
846
847/// Frame messages affect frame generation (applied after building the scene).
848#[derive(Clone, Deserialize, Serialize)]
849pub enum FrameMsg {
850    ///
851    UpdateEpoch(PipelineId, Epoch),
852    ///
853    HitTest(Option<PipelineId>, WorldPoint, HitTestFlags, MsgSender<HitTestResult>),
854    ///
855    SetPan(DeviceIntPoint),
856    ///
857    Scroll(ScrollLocation, WorldPoint),
858    ///
859    ScrollNodeWithId(LayoutPoint, di::ExternalScrollId, ScrollClamping),
860    ///
861    GetScrollNodeState(MsgSender<Vec<ScrollNodeState>>),
862    ///
863    UpdateDynamicProperties(DynamicProperties),
864    ///
865    AppendDynamicProperties(DynamicProperties),
866    ///
867    SetPinchZoom(ZoomFactor),
868    ///
869    SetIsTransformAsyncZooming(bool, PropertyBindingId),
870}
871
872impl fmt::Debug for SceneMsg {
873    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
874        f.write_str(match *self {
875            SceneMsg::UpdateEpoch(..) => "SceneMsg::UpdateEpoch",
876            SceneMsg::SetDisplayList { .. } => "SceneMsg::SetDisplayList",
877            SceneMsg::SetPageZoom(..) => "SceneMsg::SetPageZoom",
878            SceneMsg::RemovePipeline(..) => "SceneMsg::RemovePipeline",
879            SceneMsg::EnableFrameOutput(..) => "SceneMsg::EnableFrameOutput",
880            SceneMsg::SetDocumentView { .. } => "SceneMsg::SetDocumentView",
881            SceneMsg::SetRootPipeline(..) => "SceneMsg::SetRootPipeline",
882            SceneMsg::SetQualitySettings { .. } => "SceneMsg::SetQualitySettings",
883        })
884    }
885}
886
887impl fmt::Debug for FrameMsg {
888    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
889        f.write_str(match *self {
890            FrameMsg::UpdateEpoch(..) => "FrameMsg::UpdateEpoch",
891            FrameMsg::HitTest(..) => "FrameMsg::HitTest",
892            FrameMsg::SetPan(..) => "FrameMsg::SetPan",
893            FrameMsg::Scroll(..) => "FrameMsg::Scroll",
894            FrameMsg::ScrollNodeWithId(..) => "FrameMsg::ScrollNodeWithId",
895            FrameMsg::GetScrollNodeState(..) => "FrameMsg::GetScrollNodeState",
896            FrameMsg::UpdateDynamicProperties(..) => "FrameMsg::UpdateDynamicProperties",
897            FrameMsg::AppendDynamicProperties(..) => "FrameMsg::AppendDynamicProperties",
898            FrameMsg::SetPinchZoom(..) => "FrameMsg::SetPinchZoom",
899            FrameMsg::SetIsTransformAsyncZooming(..) => "FrameMsg::SetIsTransformAsyncZooming",
900        })
901    }
902}
903
904bitflags!{
905    /// Bit flags for WR stages to store in a capture.
906    // Note: capturing `FRAME` without `SCENE` is not currently supported.
907    #[derive(Deserialize, Serialize)]
908    pub struct CaptureBits: u8 {
909        ///
910        const SCENE = 0x1;
911        ///
912        const FRAME = 0x2;
913    }
914}
915
916bitflags!{
917    /// Mask for clearing caches in debug commands.
918    #[derive(Deserialize, Serialize)]
919    pub struct ClearCache: u8 {
920        ///
921        const IMAGES = 0b1;
922        ///
923        const GLYPHS = 0b01;
924        ///
925        const GLYPH_DIMENSIONS = 0b001;
926        ///
927        const RENDER_TASKS = 0b0001;
928        ///
929        const TEXTURE_CACHE = 0b00001;
930        ///
931        const RASTERIZED_BLOBS = 0b000001;
932    }
933}
934
935/// Information about a loaded capture of each document
936/// that is returned by `RenderBackend`.
937#[derive(Clone, Debug, Deserialize, Serialize)]
938pub struct CapturedDocument {
939    ///
940    pub document_id: DocumentId,
941    ///
942    pub root_pipeline_id: Option<PipelineId>,
943}
944
945/// Update of the state of built-in debugging facilities.
946#[derive(Clone, Deserialize, Serialize)]
947pub enum DebugCommand {
948    /// Sets the provided debug flags.
949    SetFlags(DebugFlags),
950    /// Configure if dual-source blending is used, if available.
951    EnableDualSourceBlending(bool),
952    /// Fetch current documents and display lists.
953    FetchDocuments,
954    /// Fetch current passes and batches.
955    FetchPasses,
956    /// Fetch clip-scroll tree.
957    FetchClipScrollTree,
958    /// Fetch render tasks.
959    FetchRenderTasks,
960    /// Fetch screenshot.
961    FetchScreenshot,
962    /// Save a capture of all the documents state.
963    SaveCapture(PathBuf, CaptureBits),
964    /// Load a capture of all the documents state.
965    LoadCapture(PathBuf, MsgSender<CapturedDocument>),
966    /// Clear cached resources, forcing them to be re-uploaded from templates.
967    ClearCaches(ClearCache),
968    /// Invalidate GPU cache, forcing the update from the CPU mirror.
969    InvalidateGpuCache,
970    /// Causes the scene builder to pause for a given amount of milliseconds each time it
971    /// processes a transaction.
972    SimulateLongSceneBuild(u32),
973    /// Causes the low priority scene builder to pause for a given amount of milliseconds
974    /// each time it processes a transaction.
975    SimulateLongLowPrioritySceneBuild(u32),
976    /// Logs transactions to a file for debugging purposes
977    SetTransactionLogging(bool),
978}
979
980/// Message sent by the `RenderApi` to the render backend thread.
981#[derive(Clone, Deserialize, Serialize)]
982pub enum ApiMsg {
983    /// Add/remove/update images and fonts.
984    UpdateResources(Vec<ResourceUpdate>),
985    /// Gets the glyph dimensions
986    GetGlyphDimensions(
987        font::FontInstanceKey,
988        Vec<font::GlyphIndex>,
989        MsgSender<Vec<Option<font::GlyphDimensions>>>,
990    ),
991    /// Gets the glyph indices from a string
992    GetGlyphIndices(font::FontKey, String, MsgSender<Vec<Option<u32>>>),
993    /// Adds a new document namespace.
994    CloneApi(MsgSender<IdNamespace>),
995    /// Adds a new document namespace.
996    CloneApiByClient(IdNamespace),
997    /// Adds a new document with given initial size.
998    AddDocument(DocumentId, DeviceIntSize, DocumentLayer),
999    /// A message targeted at a particular document.
1000    UpdateDocuments(Vec<DocumentId>, Vec<TransactionMsg>),
1001    /// Deletes an existing document.
1002    DeleteDocument(DocumentId),
1003    /// An opaque handle that must be passed to the render notifier. It is used by Gecko
1004    /// to forward gecko-specific messages to the render thread preserving the ordering
1005    /// within the other messages.
1006    ExternalEvent(ExternalEvent),
1007    /// Removes all resources associated with a namespace.
1008    ClearNamespace(IdNamespace),
1009    /// Flush from the caches anything that isn't necessary, to free some memory.
1010    MemoryPressure,
1011    /// Collects a memory report.
1012    ReportMemory(MsgSender<Box<MemoryReport>>),
1013    /// Change debugging options.
1014    DebugCommand(DebugCommand),
1015    /// Wakes the render backend's event loop up. Needed when an event is communicated
1016    /// through another channel.
1017    WakeUp,
1018    /// See `RenderApi::wake_scene_builder`.
1019    WakeSceneBuilder,
1020    /// Block until a round-trip to the scene builder thread has completed. This
1021    /// ensures that any transactions (including ones deferred to the scene
1022    /// builder thread) have been processed.
1023    FlushSceneBuilder(MsgSender<()>),
1024    /// Shut the WebRender instance down.
1025    ShutDown(Option<MsgSender<()>>),
1026}
1027
1028impl fmt::Debug for ApiMsg {
1029    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1030        f.write_str(match *self {
1031            ApiMsg::UpdateResources(..) => "ApiMsg::UpdateResources",
1032            ApiMsg::GetGlyphDimensions(..) => "ApiMsg::GetGlyphDimensions",
1033            ApiMsg::GetGlyphIndices(..) => "ApiMsg::GetGlyphIndices",
1034            ApiMsg::CloneApi(..) => "ApiMsg::CloneApi",
1035            ApiMsg::CloneApiByClient(..) => "ApiMsg::CloneApiByClient",
1036            ApiMsg::AddDocument(..) => "ApiMsg::AddDocument",
1037            ApiMsg::UpdateDocuments(..) => "ApiMsg::UpdateDocuments",
1038            ApiMsg::DeleteDocument(..) => "ApiMsg::DeleteDocument",
1039            ApiMsg::ExternalEvent(..) => "ApiMsg::ExternalEvent",
1040            ApiMsg::ClearNamespace(..) => "ApiMsg::ClearNamespace",
1041            ApiMsg::MemoryPressure => "ApiMsg::MemoryPressure",
1042            ApiMsg::ReportMemory(..) => "ApiMsg::ReportMemory",
1043            ApiMsg::DebugCommand(..) => "ApiMsg::DebugCommand",
1044            ApiMsg::ShutDown(..) => "ApiMsg::ShutDown",
1045            ApiMsg::WakeUp => "ApiMsg::WakeUp",
1046            ApiMsg::WakeSceneBuilder => "ApiMsg::WakeSceneBuilder",
1047            ApiMsg::FlushSceneBuilder(..) => "ApiMsg::FlushSceneBuilder",
1048        })
1049    }
1050}
1051
1052/// An epoch identifies the state of a pipeline in time.
1053///
1054/// This is mostly used as a synchronization mechanism to observe how/when particular pipeline
1055/// updates propagate through WebRender and are applied at various stages.
1056#[repr(C)]
1057#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
1058pub struct Epoch(pub u32);
1059
1060impl Epoch {
1061    /// Magic invalid epoch value.
1062    pub fn invalid() -> Epoch {
1063        Epoch(u32::MAX)
1064    }
1065}
1066
1067/// ID namespaces uniquely identify different users of WebRender's API.
1068///
1069/// For example in Gecko each content process uses a separate id namespace.
1070#[repr(C)]
1071#[derive(Clone, Copy, Debug, Default, Eq, MallocSizeOf, PartialEq, Hash, Ord, PartialOrd, PeekPoke)]
1072#[derive(Deserialize, Serialize)]
1073pub struct IdNamespace(pub u32);
1074
1075/// A key uniquely identifying a WebRender document.
1076///
1077/// Instances can manage one or several documents (using the same render backend thread).
1078/// Each document will internally correspond to a single scene, and scenes are made of
1079/// one or several pipelines.
1080#[repr(C)]
1081#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
1082pub struct DocumentId {
1083    ///
1084    pub namespace_id: IdNamespace,
1085    ///
1086    pub id: u32,
1087}
1088
1089impl DocumentId {
1090    ///
1091    pub fn new(namespace_id: IdNamespace, id: u32) -> Self {
1092        DocumentId {
1093            namespace_id,
1094            id,
1095        }
1096    }
1097
1098    ///
1099    pub const INVALID: DocumentId = DocumentId { namespace_id: IdNamespace(0), id: 0 };
1100}
1101
1102/// This type carries no valuable semantics for WR. However, it reflects the fact that
1103/// clients (Servo) may generate pipelines by different semi-independent sources.
1104/// These pipelines still belong to the same `IdNamespace` and the same `DocumentId`.
1105/// Having this extra Id field enables them to generate `PipelineId` without collision.
1106pub type PipelineSourceId = u32;
1107
1108/// From the point of view of WR, `PipelineId` is completely opaque and generic as long as
1109/// it's clonable, serializable, comparable, and hashable.
1110#[repr(C)]
1111#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
1112pub struct PipelineId(pub PipelineSourceId, pub u32);
1113
1114impl Default for PipelineId {
1115    fn default() -> Self {
1116        PipelineId::dummy()
1117    }
1118}
1119
1120impl PipelineId {
1121    ///
1122    pub fn dummy() -> Self {
1123        PipelineId(0, 0)
1124    }
1125}
1126
1127///
1128#[derive(Copy, Clone, Debug, MallocSizeOf, Serialize, Deserialize)]
1129pub enum ClipIntern {}
1130
1131///
1132#[derive(Copy, Clone, Debug, MallocSizeOf, Serialize, Deserialize)]
1133pub enum FilterDataIntern {}
1134
1135/// Information specific to a primitive type that
1136/// uniquely identifies a primitive template by key.
1137#[derive(Debug, Clone, Eq, MallocSizeOf, PartialEq, Hash, Serialize, Deserialize)]
1138pub enum PrimitiveKeyKind {
1139    /// Clear an existing rect, used for special effects on some platforms.
1140    Clear,
1141    ///
1142    Rectangle {
1143        ///
1144        color: ColorU,
1145    },
1146}
1147
1148/// Meta-macro to enumerate the various interner identifiers and types.
1149///
1150/// IMPORTANT: Keep this synchronized with the list in mozilla-central located at
1151/// gfx/webrender_bindings/webrender_ffi.h
1152///
1153/// Note that this could be a lot less verbose if concat_idents! were stable. :-(
1154#[macro_export]
1155macro_rules! enumerate_interners {
1156    ($macro_name: ident) => {
1157        $macro_name! {
1158            clip: ClipIntern,
1159            prim: PrimitiveKeyKind,
1160            normal_border: NormalBorderPrim,
1161            image_border: ImageBorder,
1162            image: Image,
1163            yuv_image: YuvImage,
1164            line_decoration: LineDecoration,
1165            linear_grad: LinearGradient,
1166            radial_grad: RadialGradient,
1167            picture: Picture,
1168            text_run: TextRun,
1169            filter_data: FilterDataIntern,
1170            backdrop: Backdrop,
1171        }
1172    }
1173}
1174
1175macro_rules! declare_interning_memory_report {
1176    ( $( $name:ident: $ty:ident, )+ ) => {
1177        ///
1178        #[repr(C)]
1179        #[derive(AddAssign, Clone, Debug, Default, Deserialize, Serialize)]
1180        pub struct InternerSubReport {
1181            $(
1182                ///
1183                pub $name: usize,
1184            )+
1185        }
1186    }
1187}
1188
1189enumerate_interners!(declare_interning_memory_report);
1190
1191/// Memory report for interning-related data structures.
1192/// cbindgen:derive-eq=false
1193#[repr(C)]
1194#[derive(Clone, Debug, Default, Deserialize, Serialize)]
1195pub struct InterningMemoryReport {
1196    ///
1197    pub interners: InternerSubReport,
1198    ///
1199    pub data_stores: InternerSubReport,
1200}
1201
1202impl ::std::ops::AddAssign for InterningMemoryReport {
1203    fn add_assign(&mut self, other: InterningMemoryReport) {
1204        self.interners += other.interners;
1205        self.data_stores += other.data_stores;
1206    }
1207}
1208
1209/// Collection of heap sizes, in bytes.
1210/// cbindgen:derive-eq=false
1211#[repr(C)]
1212#[allow(missing_docs)]
1213#[derive(AddAssign, Clone, Debug, Default, Deserialize, Serialize)]
1214pub struct MemoryReport {
1215    //
1216    // CPU Memory.
1217    //
1218    pub clip_stores: usize,
1219    pub gpu_cache_metadata: usize,
1220    pub gpu_cache_cpu_mirror: usize,
1221    pub render_tasks: usize,
1222    pub hit_testers: usize,
1223    pub fonts: usize,
1224    pub images: usize,
1225    pub rasterized_blobs: usize,
1226    pub shader_cache: usize,
1227    pub interning: InterningMemoryReport,
1228
1229    //
1230    // GPU memory.
1231    //
1232    pub gpu_cache_textures: usize,
1233    pub vertex_data_textures: usize,
1234    pub render_target_textures: usize,
1235    pub texture_cache_textures: usize,
1236    pub depth_target_textures: usize,
1237    pub swap_chain: usize,
1238}
1239
1240/// A C function that takes a pointer to a heap allocation and returns its size.
1241///
1242/// This is borrowed from the malloc_size_of crate, upon which we want to avoid
1243/// a dependency from WebRender.
1244pub type VoidPtrToSizeFn = unsafe extern "C" fn(ptr: *const c_void) -> usize;
1245
1246#[repr(C)]
1247#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
1248struct ResourceId(pub u32);
1249
1250/// An opaque pointer-sized value.
1251#[repr(C)]
1252#[derive(Clone, Deserialize, Serialize)]
1253pub struct ExternalEvent {
1254    raw: usize,
1255}
1256
1257unsafe impl Send for ExternalEvent {}
1258
1259impl ExternalEvent {
1260    /// Creates the event from an opaque pointer-sized value.
1261    pub fn from_raw(raw: usize) -> Self {
1262        ExternalEvent { raw }
1263    }
1264    /// Consumes self to make it obvious that the event should be forwarded only once.
1265    pub fn unwrap(self) -> usize {
1266        self.raw
1267    }
1268}
1269
1270/// Describe whether or not scrolling should be clamped by the content bounds.
1271#[derive(Clone, Deserialize, Serialize)]
1272pub enum ScrollClamping {
1273    ///
1274    ToContentBounds,
1275    ///
1276    NoClamping,
1277}
1278
1279/// Allows the API to communicate with WebRender.
1280///
1281/// This object is created along with the `Renderer` and it's main use from a
1282/// user perspective is to create one or several `RenderApi` objects.
1283#[derive(Clone, Deserialize, Serialize)]
1284pub struct RenderApiSender {
1285    api_sender: MsgSender<ApiMsg>,
1286    payload_sender: PayloadSender,
1287}
1288
1289impl RenderApiSender {
1290    /// Used internally by the `Renderer`.
1291    pub fn new(api_sender: MsgSender<ApiMsg>, payload_sender: PayloadSender) -> Self {
1292        RenderApiSender {
1293            api_sender,
1294            payload_sender,
1295        }
1296    }
1297
1298    /// Creates a new resource API object with a dedicated namespace.
1299    pub fn create_api(&self) -> RenderApi {
1300        let (sync_tx, sync_rx) =
1301            channel::msg_channel().expect("Failed to create channel");
1302        let msg = ApiMsg::CloneApi(sync_tx);
1303        self.api_sender.send(msg).expect("Failed to send CloneApi message");
1304        let namespace_id = match sync_rx.recv() {
1305            Ok(id) => id,
1306            Err(e) => {
1307                // This is used to discover the underlying cause of https://github.com/servo/servo/issues/13480.
1308                let webrender_is_alive = self.api_sender.send(ApiMsg::WakeUp);
1309                if webrender_is_alive.is_err() {
1310                    panic!("WebRender was shut down before processing CloneApi: {}", e);
1311                } else {
1312                    panic!("CloneApi message response was dropped while WebRender was still alive: {}", e);
1313                }
1314            }
1315        };
1316        RenderApi {
1317            api_sender: self.api_sender.clone(),
1318            payload_sender: self.payload_sender.clone(),
1319            namespace_id,
1320            next_id: Cell::new(ResourceId(0)),
1321        }
1322    }
1323
1324    /// Creates a new resource API object with a dedicated namespace.
1325    /// Namespace id is allocated by client.
1326    ///
1327    /// The function could be used only when RendererOptions::namespace_alloc_by_client is true.
1328    /// When the option is true, create_api() could not be used to prevent namespace id conflict.
1329    pub fn create_api_by_client(&self, namespace_id: IdNamespace) -> RenderApi {
1330        let msg = ApiMsg::CloneApiByClient(namespace_id);
1331        self.api_sender.send(msg).expect("Failed to send CloneApiByClient message");
1332        RenderApi {
1333            api_sender: self.api_sender.clone(),
1334            payload_sender: self.payload_sender.clone(),
1335            namespace_id,
1336            next_id: Cell::new(ResourceId(0)),
1337        }
1338    }
1339}
1340
1341bitflags! {
1342    /// Flags to enable/disable various builtin debugging tools.
1343    #[repr(C)]
1344    #[derive(Default, Deserialize, MallocSizeOf, Serialize)]
1345    pub struct DebugFlags: u32 {
1346        /// Display the frame profiler on screen.
1347        const PROFILER_DBG          = 1 << 0;
1348        /// Display intermediate render targets on screen.
1349        const RENDER_TARGET_DBG     = 1 << 1;
1350        /// Display all texture cache pages on screen.
1351        const TEXTURE_CACHE_DBG     = 1 << 2;
1352        /// Display GPU timing results.
1353        const GPU_TIME_QUERIES      = 1 << 3;
1354        /// Query the number of pixels that pass the depth test divided and show it
1355        /// in the profiler as a percentage of the number of pixels in the screen
1356        /// (window width times height).
1357        const GPU_SAMPLE_QUERIES    = 1 << 4;
1358        /// Render each quad with their own draw call.
1359        ///
1360        /// Terrible for performance but can help with understanding the drawing
1361        /// order when inspecting renderdoc or apitrace recordings.
1362        const DISABLE_BATCHING      = 1 << 5;
1363        /// Display the pipeline epochs.
1364        const EPOCHS                = 1 << 6;
1365        /// Reduce the amount of information displayed by the profiler so that
1366        /// it occupies less screen real-estate.
1367        const COMPACT_PROFILER      = 1 << 7;
1368        /// Print driver messages to stdout.
1369        const ECHO_DRIVER_MESSAGES  = 1 << 8;
1370        /// Show an indicator that moves every time a frame is rendered.
1371        const NEW_FRAME_INDICATOR   = 1 << 9;
1372        /// Show an indicator that moves every time a scene is built.
1373        const NEW_SCENE_INDICATOR   = 1 << 10;
1374        /// Show an overlay displaying overdraw amount.
1375        const SHOW_OVERDRAW         = 1 << 11;
1376        /// Display the contents of GPU cache.
1377        const GPU_CACHE_DBG         = 1 << 12;
1378        /// Show a red bar that moves each time a slow frame is detected.
1379        const SLOW_FRAME_INDICATOR  = 1 << 13;
1380        /// Clear evicted parts of the texture cache for debugging purposes.
1381        const TEXTURE_CACHE_DBG_CLEAR_EVICTED = 1 << 14;
1382        /// Show picture caching debug overlay
1383        const PICTURE_CACHING_DBG   = 1 << 15;
1384        /// Highlight all primitives with colors based on kind.
1385        const PRIMITIVE_DBG = 1 << 16;
1386        /// Draw a zoom widget showing part of the framebuffer zoomed in.
1387        const ZOOM_DBG = 1 << 17;
1388        /// Scale the debug renderer down for a smaller screen. This will disrupt
1389        /// any mapping between debug display items and page content, so shouldn't
1390        /// be used with overlays like the picture caching or primitive display.
1391        const SMALL_SCREEN = 1 << 18;
1392        /// Disable various bits of the WebRender pipeline, to help narrow
1393        /// down where slowness might be coming from.
1394        const DISABLE_OPAQUE_PASS = 1 << 19;
1395        ///
1396        const DISABLE_ALPHA_PASS = 1 << 20;
1397        ///
1398        const DISABLE_CLIP_MASKS = 1 << 21;
1399        ///
1400        const DISABLE_TEXT_PRIMS = 1 << 22;
1401        ///
1402        const DISABLE_GRADIENT_PRIMS = 1 << 23;
1403        ///
1404        const OBSCURE_IMAGES = 1 << 24;
1405        /// Taint the transparent area of the glyphs with a random opacity to easily
1406        /// see when glyphs are re-rasterized.
1407        const GLYPH_FLASHING = 1 << 25;
1408        /// The profiler only displays information that is out of the ordinary.
1409        const SMART_PROFILER        = 1 << 26;
1410        /// Dynamically control whether picture caching is enabled.
1411        const DISABLE_PICTURE_CACHING = 1 << 27;
1412        /// If set, dump picture cache invalidation debug to console.
1413        const INVALIDATION_DBG = 1 << 28;
1414    }
1415}
1416
1417/// The main entry point to interact with WebRender.
1418pub struct RenderApi {
1419    api_sender: MsgSender<ApiMsg>,
1420    payload_sender: PayloadSender,
1421    namespace_id: IdNamespace,
1422    next_id: Cell<ResourceId>,
1423}
1424
1425impl RenderApi {
1426    /// Returns the namespace ID used by this API object.
1427    pub fn get_namespace_id(&self) -> IdNamespace {
1428        self.namespace_id
1429    }
1430
1431    ///
1432    pub fn clone_sender(&self) -> RenderApiSender {
1433        RenderApiSender::new(self.api_sender.clone(), self.payload_sender.clone())
1434    }
1435
1436    /// Add a document to the WebRender instance.
1437    ///
1438    /// Instances can manage one or several documents (using the same render backend thread).
1439    /// Each document will internally correspond to a single scene, and scenes are made of
1440    /// one or several pipelines.
1441    pub fn add_document(&self, initial_size: DeviceIntSize, layer: DocumentLayer) -> DocumentId {
1442        let new_id = self.next_unique_id();
1443        self.add_document_with_id(initial_size, layer, new_id)
1444    }
1445
1446    /// See `add_document`
1447    pub fn add_document_with_id(&self,
1448                                initial_size: DeviceIntSize,
1449                                layer: DocumentLayer,
1450                                id: u32) -> DocumentId {
1451        let document_id = DocumentId::new(self.namespace_id, id);
1452
1453        let msg = ApiMsg::AddDocument(document_id, initial_size, layer);
1454        self.api_sender.send(msg).unwrap();
1455
1456        document_id
1457    }
1458
1459    /// Delete a document.
1460    pub fn delete_document(&self, document_id: DocumentId) {
1461        let msg = ApiMsg::DeleteDocument(document_id);
1462        self.api_sender.send(msg).unwrap();
1463    }
1464
1465    /// Generate a new font key
1466    pub fn generate_font_key(&self) -> font::FontKey {
1467        let new_id = self.next_unique_id();
1468        font::FontKey::new(self.namespace_id, new_id)
1469    }
1470
1471    /// Generate a new font instance key
1472    pub fn generate_font_instance_key(&self) -> font::FontInstanceKey {
1473        let new_id = self.next_unique_id();
1474        font::FontInstanceKey::new(self.namespace_id, new_id)
1475    }
1476
1477    /// Gets the dimensions for the supplied glyph keys
1478    ///
1479    /// Note: Internally, the internal texture cache doesn't store
1480    /// 'empty' textures (height or width = 0)
1481    /// This means that glyph dimensions e.g. for spaces (' ') will mostly be None.
1482    pub fn get_glyph_dimensions(
1483        &self,
1484        font: font::FontInstanceKey,
1485        glyph_indices: Vec<font::GlyphIndex>,
1486    ) -> Vec<Option<font::GlyphDimensions>> {
1487        let (tx, rx) = channel::msg_channel().unwrap();
1488        let msg = ApiMsg::GetGlyphDimensions(font, glyph_indices, tx);
1489        self.api_sender.send(msg).unwrap();
1490        rx.recv().unwrap()
1491    }
1492
1493    /// Gets the glyph indices for the supplied string. These
1494    /// can be used to construct GlyphKeys.
1495    pub fn get_glyph_indices(&self, font_key: font::FontKey, text: &str) -> Vec<Option<u32>> {
1496        let (tx, rx) = channel::msg_channel().unwrap();
1497        let msg = ApiMsg::GetGlyphIndices(font_key, text.to_string(), tx);
1498        self.api_sender.send(msg).unwrap();
1499        rx.recv().unwrap()
1500    }
1501
1502    /// Creates an `ImageKey`.
1503    pub fn generate_image_key(&self) -> ImageKey {
1504        let new_id = self.next_unique_id();
1505        ImageKey::new(self.namespace_id, new_id)
1506    }
1507
1508    /// Creates a `BlobImageKey`.
1509    pub fn generate_blob_image_key(&self) -> BlobImageKey {
1510        BlobImageKey(self.generate_image_key())
1511    }
1512
1513    /// Add/remove/update resources such as images and fonts.
1514    pub fn update_resources(&self, resources: Vec<ResourceUpdate>) {
1515        if resources.is_empty() {
1516            return;
1517        }
1518        self.api_sender
1519            .send(ApiMsg::UpdateResources(resources))
1520            .unwrap();
1521    }
1522
1523    /// A Gecko-specific notification mechanism to get some code executed on the
1524    /// `Renderer`'s thread, mostly replaced by `NotificationHandler`. You should
1525    /// probably use the latter instead.
1526    pub fn send_external_event(&self, evt: ExternalEvent) {
1527        let msg = ApiMsg::ExternalEvent(evt);
1528        self.api_sender.send(msg).unwrap();
1529    }
1530
1531    /// Notify WebRender that now is a good time to flush caches and release
1532    /// as much memory as possible.
1533    pub fn notify_memory_pressure(&self) {
1534        self.api_sender.send(ApiMsg::MemoryPressure).unwrap();
1535    }
1536
1537    /// Synchronously requests memory report.
1538    pub fn report_memory(&self) -> MemoryReport {
1539        let (tx, rx) = channel::msg_channel().unwrap();
1540        self.api_sender.send(ApiMsg::ReportMemory(tx)).unwrap();
1541        *rx.recv().unwrap()
1542    }
1543
1544    /// Update debugging flags.
1545    pub fn set_debug_flags(&self, flags: DebugFlags) {
1546        let cmd = DebugCommand::SetFlags(flags);
1547        self.api_sender.send(ApiMsg::DebugCommand(cmd)).unwrap();
1548    }
1549
1550    /// Shut the WebRender instance down.
1551    pub fn shut_down(&self, synchronously: bool) {
1552        if synchronously {
1553            let (tx, rx) = channel::msg_channel().unwrap();
1554            self.api_sender.send(ApiMsg::ShutDown(Some(tx))).unwrap();
1555            rx.recv().unwrap();
1556        } else {
1557            self.api_sender.send(ApiMsg::ShutDown(None)).unwrap();
1558        }
1559    }
1560
1561    /// Create a new unique key that can be used for
1562    /// animated property bindings.
1563    pub fn generate_property_binding_key<T: Copy>(&self) -> PropertyBindingKey<T> {
1564        let new_id = self.next_unique_id();
1565        PropertyBindingKey {
1566            id: PropertyBindingId {
1567                namespace: self.namespace_id,
1568                uid: new_id,
1569            },
1570            _phantom: PhantomData,
1571        }
1572    }
1573
1574    #[inline]
1575    fn next_unique_id(&self) -> u32 {
1576        let ResourceId(id) = self.next_id.get();
1577        self.next_id.set(ResourceId(id + 1));
1578        id
1579    }
1580
1581    // For use in Wrench only
1582    #[doc(hidden)]
1583    pub fn send_message(&self, msg: ApiMsg) {
1584        self.api_sender.send(msg).unwrap();
1585    }
1586
1587    // For use in Wrench only
1588    #[doc(hidden)]
1589    pub fn send_payload(&self, data: &[u8]) {
1590        self.payload_sender
1591            .send_payload(Payload::from_data(data))
1592            .unwrap();
1593    }
1594
1595    /// A helper method to send document messages.
1596    fn send_scene_msg(&self, document_id: DocumentId, msg: SceneMsg) {
1597        // This assertion fails on Servo use-cases, because it creates different
1598        // `RenderApi` instances for layout and compositor.
1599        //assert_eq!(document_id.0, self.namespace_id);
1600        self.api_sender
1601            .send(ApiMsg::UpdateDocuments(vec![document_id], vec![TransactionMsg::scene_message(msg)]))
1602            .unwrap()
1603    }
1604
1605    /// A helper method to send document messages.
1606    fn send_frame_msg(&self, document_id: DocumentId, msg: FrameMsg) {
1607        // This assertion fails on Servo use-cases, because it creates different
1608        // `RenderApi` instances for layout and compositor.
1609        //assert_eq!(document_id.0, self.namespace_id);
1610        self.api_sender
1611            .send(ApiMsg::UpdateDocuments(vec![document_id], vec![TransactionMsg::frame_message(msg)]))
1612            .unwrap()
1613    }
1614
1615    /// Send a transaction to WebRender.
1616    pub fn send_transaction(&self, document_id: DocumentId, transaction: Transaction) {
1617        let (msg, payloads) = transaction.finalize();
1618        for payload in payloads {
1619            self.payload_sender.send_payload(payload).unwrap();
1620        }
1621        self.api_sender.send(ApiMsg::UpdateDocuments(vec![document_id], vec![msg])).unwrap();
1622    }
1623
1624    /// Send multiple transactions.
1625    pub fn send_transactions(&self, document_ids: Vec<DocumentId>, mut transactions: Vec<Transaction>) {
1626        debug_assert!(document_ids.len() == transactions.len());
1627        let length = document_ids.len();
1628        let (msgs, mut document_payloads) = transactions.drain(..)
1629            .fold((Vec::with_capacity(length), Vec::with_capacity(length)),
1630                |(mut msgs, mut document_payloads), transaction| {
1631                    let (msg, payloads) = transaction.finalize();
1632                    msgs.push(msg);
1633                    document_payloads.push(payloads);
1634                    (msgs, document_payloads)
1635                });
1636        for payload in document_payloads.drain(..).flatten() {
1637            self.payload_sender.send_payload(payload).unwrap();
1638        }
1639        self.api_sender.send(ApiMsg::UpdateDocuments(document_ids, msgs)).unwrap();
1640    }
1641
1642    /// Does a hit test on display items in the specified document, at the given
1643    /// point. If a pipeline_id is specified, it is used to further restrict the
1644    /// hit results so that only items inside that pipeline are matched. If the
1645    /// HitTestFlags argument contains the FIND_ALL flag, then the vector of hit
1646    /// results will contain all display items that match, ordered from front
1647    /// to back.
1648    pub fn hit_test(&self,
1649                    document_id: DocumentId,
1650                    pipeline_id: Option<PipelineId>,
1651                    point: WorldPoint,
1652                    flags: HitTestFlags)
1653                    -> HitTestResult {
1654        let (tx, rx) = channel::msg_channel().unwrap();
1655
1656        self.send_frame_msg(
1657            document_id,
1658            FrameMsg::HitTest(pipeline_id, point, flags, tx)
1659        );
1660        rx.recv().unwrap()
1661    }
1662
1663    /// Setup the output region in the framebuffer for a given document.
1664    pub fn set_document_view(
1665        &self,
1666        document_id: DocumentId,
1667        device_rect: DeviceIntRect,
1668        device_pixel_ratio: f32,
1669    ) {
1670        self.send_scene_msg(
1671            document_id,
1672            SceneMsg::SetDocumentView { device_rect, device_pixel_ratio },
1673        );
1674    }
1675
1676    /// Setup the output region in the framebuffer for a given document.
1677    /// Enable copying of the output of this pipeline id to
1678    /// an external texture for callers to consume.
1679    pub fn enable_frame_output(
1680        &self,
1681        document_id: DocumentId,
1682        pipeline_id: PipelineId,
1683        enable: bool,
1684    ) {
1685        self.send_scene_msg(
1686            document_id,
1687            SceneMsg::EnableFrameOutput(pipeline_id, enable),
1688        );
1689    }
1690
1691    ///
1692    pub fn get_scroll_node_state(&self, document_id: DocumentId) -> Vec<ScrollNodeState> {
1693        let (tx, rx) = channel::msg_channel().unwrap();
1694        self.send_frame_msg(document_id, FrameMsg::GetScrollNodeState(tx));
1695        rx.recv().unwrap()
1696    }
1697
1698    // Some internal scheduling magic that leaked into the API.
1699    // Buckle up and see APZUpdater.cpp for more info about what this is about.
1700    #[doc(hidden)]
1701    pub fn wake_scene_builder(&self) {
1702        self.send_message(ApiMsg::WakeSceneBuilder);
1703    }
1704
1705    /// Block until a round-trip to the scene builder thread has completed. This
1706    /// ensures that any transactions (including ones deferred to the scene
1707    /// builder thread) have been processed.
1708    pub fn flush_scene_builder(&self) {
1709        let (tx, rx) = channel::msg_channel().unwrap();
1710        self.send_message(ApiMsg::FlushSceneBuilder(tx));
1711        rx.recv().unwrap(); // block until done
1712    }
1713
1714    /// Save a capture of the current frame state for debugging.
1715    pub fn save_capture(&self, path: PathBuf, bits: CaptureBits) {
1716        let msg = ApiMsg::DebugCommand(DebugCommand::SaveCapture(path, bits));
1717        self.send_message(msg);
1718    }
1719
1720    /// Load a capture of the current frame state for debugging.
1721    pub fn load_capture(&self, path: PathBuf) -> Vec<CapturedDocument> {
1722        // First flush the scene builder otherwise async scenes might clobber
1723        // the capture we are about to load.
1724        self.flush_scene_builder();
1725
1726        let (tx, rx) = channel::msg_channel().unwrap();
1727        let msg = ApiMsg::DebugCommand(DebugCommand::LoadCapture(path, tx));
1728        self.send_message(msg);
1729
1730        let mut documents = Vec::new();
1731        while let Ok(captured_doc) = rx.recv() {
1732            documents.push(captured_doc);
1733        }
1734        documents
1735    }
1736
1737    /// Update the state of builtin debugging facilities.
1738    pub fn send_debug_cmd(&self, cmd: DebugCommand) {
1739        let msg = ApiMsg::DebugCommand(cmd);
1740        self.send_message(msg);
1741    }
1742}
1743
1744impl Drop for RenderApi {
1745    fn drop(&mut self) {
1746        let msg = ApiMsg::ClearNamespace(self.namespace_id);
1747        let _ = self.api_sender.send(msg);
1748    }
1749}
1750
1751///
1752#[derive(Clone, Deserialize, Serialize)]
1753pub struct ScrollNodeState {
1754    ///
1755    pub id: di::ExternalScrollId,
1756    ///
1757    pub scroll_offset: LayoutVector2D,
1758}
1759
1760///
1761#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
1762pub enum ScrollLocation {
1763    /// Scroll by a certain amount.
1764    Delta(LayoutVector2D),
1765    /// Scroll to very top of element.
1766    Start,
1767    /// Scroll to very bottom of element.
1768    End,
1769}
1770
1771/// Represents a zoom factor.
1772#[derive(Clone, Copy, Serialize, Deserialize, Debug)]
1773pub struct ZoomFactor(f32);
1774
1775impl ZoomFactor {
1776    /// Construct a new zoom factor.
1777    pub fn new(scale: f32) -> Self {
1778        ZoomFactor(scale)
1779    }
1780
1781    /// Get the zoom factor as an untyped float.
1782    pub fn get(self) -> f32 {
1783        self.0
1784    }
1785}
1786
1787/// A key to identify an animated property binding.
1788#[repr(C)]
1789#[derive(Clone, Copy, Debug, Default, Deserialize, MallocSizeOf, PartialEq, Serialize, Eq, Hash, PeekPoke)]
1790pub struct PropertyBindingId {
1791    namespace: IdNamespace,
1792    uid: u32,
1793}
1794
1795impl PropertyBindingId {
1796    /// Constructor.
1797    pub fn new(value: u64) -> Self {
1798        PropertyBindingId {
1799            namespace: IdNamespace((value >> 32) as u32),
1800            uid: value as u32,
1801        }
1802    }
1803}
1804
1805/// A unique key that is used for connecting animated property
1806/// values to bindings in the display list.
1807#[repr(C)]
1808#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
1809pub struct PropertyBindingKey<T> {
1810    ///
1811    pub id: PropertyBindingId,
1812    _phantom: PhantomData<T>,
1813}
1814
1815/// Construct a property value from a given key and value.
1816impl<T: Copy> PropertyBindingKey<T> {
1817    ///
1818    pub fn with(self, value: T) -> PropertyValue<T> {
1819        PropertyValue { key: self, value }
1820    }
1821}
1822
1823impl<T> PropertyBindingKey<T> {
1824    /// Constructor.
1825    pub fn new(value: u64) -> Self {
1826        PropertyBindingKey {
1827            id: PropertyBindingId::new(value),
1828            _phantom: PhantomData,
1829        }
1830    }
1831}
1832
1833/// A binding property can either be a specific value
1834/// (the normal, non-animated case) or point to a binding location
1835/// to fetch the current value from.
1836/// Note that Binding has also a non-animated value, the value is
1837/// used for the case where the animation is still in-delay phase
1838/// (i.e. the animation doesn't produce any animation values).
1839#[repr(C)]
1840#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize, PeekPoke)]
1841pub enum PropertyBinding<T> {
1842    /// Non-animated value.
1843    Value(T),
1844    /// Animated binding.
1845    Binding(PropertyBindingKey<T>, T),
1846}
1847
1848impl<T: Default> Default for PropertyBinding<T> {
1849    fn default() -> Self {
1850        PropertyBinding::Value(Default::default())
1851    }
1852}
1853
1854impl<T> From<T> for PropertyBinding<T> {
1855    fn from(value: T) -> PropertyBinding<T> {
1856        PropertyBinding::Value(value)
1857    }
1858}
1859
1860/// The current value of an animated property. This is
1861/// supplied by the calling code.
1862#[derive(Clone, Copy, Debug, Deserialize, Serialize, PartialEq)]
1863pub struct PropertyValue<T> {
1864    ///
1865    pub key: PropertyBindingKey<T>,
1866    ///
1867    pub value: T,
1868}
1869
1870/// When using `generate_frame()`, a list of `PropertyValue` structures
1871/// can optionally be supplied to provide the current value of any
1872/// animated properties.
1873#[derive(Clone, Deserialize, Serialize, Debug, PartialEq, Default)]
1874pub struct DynamicProperties {
1875    ///
1876    pub transforms: Vec<PropertyValue<LayoutTransform>>,
1877    ///
1878    pub floats: Vec<PropertyValue<f32>>,
1879}
1880
1881/// A handler to integrate WebRender with the thread that contains the `Renderer`.
1882pub trait RenderNotifier: Send {
1883    ///
1884    fn clone(&self) -> Box<dyn RenderNotifier>;
1885    /// Wake the thread containing the `Renderer` up (after updates have been put
1886    /// in the renderer's queue).
1887    fn wake_up(&self);
1888    /// Notify the thread containing the `Renderer` that a new frame is ready.
1889    fn new_frame_ready(&self, _: DocumentId, scrolled: bool, composite_needed: bool, render_time_ns: Option<u64>);
1890    /// A Gecko-specific notification mechanism to get some code executed on the
1891    /// `Renderer`'s thread, mostly replaced by `NotificationHandler`. You should
1892    /// probably use the latter instead.
1893    fn external_event(&self, _evt: ExternalEvent) {
1894        unimplemented!()
1895    }
1896    /// Notify the thread containing the `Renderer` that the render backend has been
1897    /// shut down.
1898    fn shut_down(&self) {}
1899}
1900
1901/// A stage of the rendering pipeline.
1902#[repr(u32)]
1903#[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
1904pub enum Checkpoint {
1905    ///
1906    SceneBuilt,
1907    ///
1908    FrameBuilt,
1909    ///
1910    FrameTexturesUpdated,
1911    ///
1912    FrameRendered,
1913    /// NotificationRequests get notified with this if they get dropped without having been
1914    /// notified. This provides the guarantee that if a request is created it will get notified.
1915    TransactionDropped,
1916}
1917
1918/// A handler to notify when a transaction reaches certain stages of the rendering
1919/// pipeline.
1920pub trait NotificationHandler : Send + Sync {
1921    /// Entry point of the handler to implement. Invoked by WebRender.
1922    fn notify(&self, when: Checkpoint);
1923}
1924
1925/// A request to notify a handler when the transaction reaches certain stages of the
1926/// rendering pipeline.
1927///
1928/// The request is guaranteed to be notified once and only once, even if the transaction
1929/// is dropped before the requested check-point.
1930pub struct NotificationRequest {
1931    handler: Option<Box<dyn NotificationHandler>>,
1932    when: Checkpoint,
1933}
1934
1935impl NotificationRequest {
1936    /// Constructor.
1937    pub fn new(when: Checkpoint, handler: Box<dyn NotificationHandler>) -> Self {
1938        NotificationRequest {
1939            handler: Some(handler),
1940            when,
1941        }
1942    }
1943
1944    /// The specified stage at which point the handler should be notified.
1945    pub fn when(&self) -> Checkpoint { self.when }
1946
1947    /// Called by WebRender at specified stages to notify the registered handler.
1948    pub fn notify(mut self) {
1949        if let Some(handler) = self.handler.take() {
1950            handler.notify(self.when);
1951        }
1952    }
1953}
1954
1955impl Drop for NotificationRequest {
1956    fn drop(&mut self) {
1957        if let Some(ref mut handler) = self.handler {
1958            handler.notify(Checkpoint::TransactionDropped);
1959        }
1960    }
1961}
1962
1963// This Clone impl yields an "empty" request because we don't want the requests
1964// to be notified twice so the request is owned by only one of the API messages
1965// (the original one) after the clone.
1966// This works in practice because the notifications requests are used for
1967// synchronization so we don't need to include them in the recording mechanism
1968// in wrench that clones the messages.
1969impl Clone for NotificationRequest {
1970    fn clone(&self) -> Self {
1971        NotificationRequest {
1972            when: self.when,
1973            handler: None,
1974        }
1975    }
1976}