tor-browser

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

lib.rs (28640B)


      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 //! The `webrender_api` crate contains an assortment types and functions used
      6 //! by WebRender consumers as well as, in many cases, WebRender itself.
      7 //!
      8 //! This separation allows Servo to parallelize compilation across `webrender`
      9 //! and other crates that depend on `webrender_api`. So in practice, we put
     10 //! things in this crate when Servo needs to use them. Firefox depends on the
     11 //! `webrender` crate directly, and so this distinction is not really relevant
     12 //! there.
     13 
     14 #![cfg_attr(feature = "nightly", feature(nonzero))]
     15 #![allow(
     16    clippy::float_cmp,
     17    clippy::too_many_arguments,
     18    clippy::unreadable_literal,
     19    clippy::new_without_default,
     20    clippy::empty_docs,
     21    clippy::manual_range_contains,
     22    unknown_lints,
     23    mismatched_lifetime_syntaxes,
     24 )]
     25 
     26 
     27 pub extern crate crossbeam_channel;
     28 pub extern crate euclid;
     29 
     30 extern crate app_units;
     31 #[macro_use]
     32 extern crate bitflags;
     33 extern crate byteorder;
     34 #[cfg(feature = "nightly")]
     35 extern crate core;
     36 #[macro_use]
     37 extern crate malloc_size_of_derive;
     38 extern crate serde;
     39 #[macro_use]
     40 extern crate serde_derive;
     41 
     42 extern crate malloc_size_of;
     43 extern crate peek_poke;
     44 
     45 pub mod channel;
     46 mod color;
     47 #[cfg(feature = "debugger")]
     48 pub mod debugger;
     49 mod display_item;
     50 mod display_item_cache;
     51 mod display_list;
     52 mod font;
     53 mod gradient_builder;
     54 mod image;
     55 mod tile_pool;
     56 pub mod units;
     57 
     58 pub use crate::color::*;
     59 pub use crate::display_item::*;
     60 pub use crate::display_item_cache::DisplayItemCache;
     61 pub use crate::display_list::*;
     62 pub use crate::font::*;
     63 pub use crate::gradient_builder::*;
     64 pub use crate::image::*;
     65 pub use crate::tile_pool::*;
     66 
     67 use crate::units::*;
     68 use crate::channel::Receiver;
     69 use std::marker::PhantomData;
     70 use std::sync::Arc;
     71 use std::os::raw::c_void;
     72 use peek_poke::PeekPoke;
     73 
     74 /// Defined here for cbindgen
     75 pub const MAX_RENDER_TASK_SIZE: i32 = 16384;
     76 
     77 /// Width and height in device pixels of image tiles.
     78 pub type TileSize = u16;
     79 
     80 /// Various settings that the caller can select based on desired tradeoffs
     81 /// between rendering quality and performance / power usage.
     82 #[derive(Copy, Clone, Deserialize, Serialize)]
     83 pub struct QualitySettings {
     84    /// If true, disable creating separate picture cache slices when the
     85    /// scroll root changes. This gives maximum opportunity to find an
     86    /// opaque background, which enables subpixel AA. However, it is
     87    /// usually significantly more expensive to render when scrolling.
     88    pub force_subpixel_aa_where_possible: bool,
     89 }
     90 
     91 impl Default for QualitySettings {
     92    fn default() -> Self {
     93        QualitySettings {
     94            // Prefer performance over maximum subpixel AA quality, since WR
     95            // already enables subpixel AA in more situations than other browsers.
     96            force_subpixel_aa_where_possible: false,
     97        }
     98    }
     99 }
    100 
    101 /// An epoch identifies the state of a pipeline in time.
    102 ///
    103 /// This is mostly used as a synchronization mechanism to observe how/when particular pipeline
    104 /// updates propagate through WebRender and are applied at various stages.
    105 #[repr(C)]
    106 #[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, Ord, PartialEq, PartialOrd, Serialize)]
    107 pub struct Epoch(pub u32);
    108 
    109 impl Epoch {
    110    /// Magic invalid epoch value.
    111    pub fn invalid() -> Epoch {
    112        Epoch(u32::MAX)
    113    }
    114 }
    115 
    116 /// ID namespaces uniquely identify different users of WebRender's API.
    117 ///
    118 /// For example in Gecko each content process uses a separate id namespace.
    119 #[repr(C)]
    120 #[derive(Clone, Copy, Debug, Default, Eq, MallocSizeOf, PartialEq, Hash, Ord, PartialOrd, PeekPoke)]
    121 #[derive(Deserialize, Serialize)]
    122 pub struct IdNamespace(pub u32);
    123 
    124 impl IdNamespace {
    125    pub const DEBUGGER: IdNamespace = IdNamespace(!0);
    126 }
    127 
    128 /// A key uniquely identifying a WebRender document.
    129 ///
    130 /// Instances can manage one or several documents (using the same render backend thread).
    131 /// Each document will internally correspond to a single scene, and scenes are made of
    132 /// one or several pipelines.
    133 #[repr(C)]
    134 #[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
    135 pub struct DocumentId {
    136    ///
    137    pub namespace_id: IdNamespace,
    138    ///
    139    pub id: u32,
    140 }
    141 
    142 impl DocumentId {
    143    ///
    144    pub fn new(namespace_id: IdNamespace, id: u32) -> Self {
    145        DocumentId {
    146            namespace_id,
    147            id,
    148        }
    149    }
    150 
    151    ///
    152    pub const INVALID: DocumentId = DocumentId { namespace_id: IdNamespace(0), id: 0 };
    153 }
    154 
    155 /// This type carries no valuable semantics for WR. However, it reflects the fact that
    156 /// clients (Servo) may generate pipelines by different semi-independent sources.
    157 /// These pipelines still belong to the same `IdNamespace` and the same `DocumentId`.
    158 /// Having this extra Id field enables them to generate `PipelineId` without collision.
    159 pub type PipelineSourceId = u32;
    160 
    161 /// From the point of view of WR, `PipelineId` is completely opaque and generic as long as
    162 /// it's clonable, serializable, comparable, and hashable.
    163 #[repr(C)]
    164 #[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
    165 pub struct PipelineId(pub PipelineSourceId, pub u32);
    166 
    167 impl Default for PipelineId {
    168    fn default() -> Self {
    169        PipelineId::dummy()
    170    }
    171 }
    172 
    173 impl PipelineId {
    174    ///
    175    pub fn dummy() -> Self {
    176        PipelineId(!0, !0)
    177    }
    178 
    179    pub const INVALID: Self = PipelineId(!0, !0);
    180 }
    181 
    182 #[repr(C)]
    183 #[derive(Clone, Copy, Debug, PartialEq, PartialOrd)]
    184 pub struct FramePublishId(pub u64);
    185 
    186 impl FramePublishId {
    187    /// Returns a FramePublishId corresponding to the first frame.
    188    ///
    189    /// Note that we use 0 as the internal id here because the current code
    190    /// increments the frame publish id just before ResultMsg::PublishDocument,
    191    /// and we want the first id to be 1.
    192    pub fn first() -> Self {
    193        FramePublishId(0)
    194    }
    195 
    196    /// Advances this FramePublishId to the next.
    197    pub fn advance(&mut self) {
    198        self.0 += 1;
    199    }
    200 
    201    /// An invalid sentinel FramePublishId, which will always compare less than
    202    /// any valid FrameId.
    203    pub const INVALID: Self = FramePublishId(0);
    204 }
    205 
    206 impl Default for FramePublishId {
    207    fn default() -> Self {
    208        FramePublishId::INVALID
    209    }
    210 }
    211 
    212 /// An opaque pointer-sized value.
    213 #[repr(C)]
    214 #[derive(Clone)]
    215 pub struct ExternalEvent {
    216    raw: usize,
    217 }
    218 
    219 unsafe impl Send for ExternalEvent {}
    220 
    221 impl ExternalEvent {
    222    /// Creates the event from an opaque pointer-sized value.
    223    pub fn from_raw(raw: usize) -> Self {
    224        ExternalEvent { raw }
    225    }
    226    /// Consumes self to make it obvious that the event should be forwarded only once.
    227    pub fn unwrap(self) -> usize {
    228        self.raw
    229    }
    230 }
    231 
    232 pub type APZScrollGeneration = u64;
    233 #[repr(C)]
    234 #[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize, Default)]
    235 pub struct SampledScrollOffset {
    236    pub offset: LayoutVector2D,
    237    pub generation: APZScrollGeneration,
    238 }
    239 
    240 /// A flag in each scrollable frame to represent whether the owner of the frame document
    241 /// has any scroll-linked effect.
    242 /// See https://firefox-source-docs.mozilla.org/performance/scroll-linked_effects.html
    243 /// for a definition of scroll-linked effect.
    244 #[repr(u8)]
    245 #[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
    246 pub enum HasScrollLinkedEffect {
    247    Yes,
    248    #[default]
    249    No,
    250 }
    251 
    252 #[repr(C)]
    253 pub struct MinimapData {
    254  pub is_root_content: bool,
    255  // All rects in local coords relative to the scrolled content's origin.
    256  pub visual_viewport: LayoutRect,
    257  pub layout_viewport: LayoutRect,
    258  pub scrollable_rect: LayoutRect,
    259  pub displayport: LayoutRect,
    260  // Populated for root content nodes only, otherwise the identity
    261  pub zoom_transform: LayoutTransform,
    262  // Populated for nodes in the subtree of a root content node
    263  // (outside such subtrees we'll have `root_content_scroll_id == 0`).
    264  // Stores the enclosing root content node's ExternalScrollId.
    265  pub root_content_pipeline_id: PipelineId,
    266  pub root_content_scroll_id: u64
    267 }
    268 
    269 #[repr(C)]
    270 pub struct FrameReadyParams {
    271    pub present: bool,
    272    pub render: bool,
    273    pub scrolled: bool,
    274    /// Firefox uses this to indicate that the frame does not participate
    275    /// in the frame throttling mechanism.
    276    /// Frames from off-screen transactions are not tracked.
    277    pub tracked: bool,
    278 }
    279 
    280 /// A handler to integrate WebRender with the thread that contains the `Renderer`.
    281 pub trait RenderNotifier: Send {
    282    ///
    283    fn clone(&self) -> Box<dyn RenderNotifier>;
    284    /// Wake the thread containing the `Renderer` up (after updates have been put
    285    /// in the renderer's queue).
    286    fn wake_up(
    287        &self,
    288        composite_needed: bool,
    289    );
    290    /// Notify the thread containing the `Renderer` that a new frame is ready.
    291    fn new_frame_ready(&self, _: DocumentId, publish_id: FramePublishId, params: &FrameReadyParams);
    292    /// A Gecko-specific notification mechanism to get some code executed on the
    293    /// `Renderer`'s thread, mostly replaced by `NotificationHandler`. You should
    294    /// probably use the latter instead.
    295    fn external_event(&self, _evt: ExternalEvent) {
    296        unimplemented!()
    297    }
    298    /// Notify the thread containing the `Renderer` that the render backend has been
    299    /// shut down.
    300    fn shut_down(&self) {}
    301 }
    302 
    303 /// A stage of the rendering pipeline.
    304 #[repr(u32)]
    305 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
    306 pub enum Checkpoint {
    307    ///
    308    SceneBuilt,
    309    ///
    310    FrameBuilt,
    311    ///
    312    FrameTexturesUpdated,
    313    ///
    314    FrameRendered,
    315    /// NotificationRequests get notified with this if they get dropped without having been
    316    /// notified. This provides the guarantee that if a request is created it will get notified.
    317    TransactionDropped,
    318 }
    319 
    320 /// A handler to notify when a transaction reaches certain stages of the rendering
    321 /// pipeline.
    322 pub trait NotificationHandler : Send + Sync {
    323    /// Entry point of the handler to implement. Invoked by WebRender.
    324    fn notify(&self, when: Checkpoint);
    325 }
    326 
    327 /// A request to notify a handler when the transaction reaches certain stages of the
    328 /// rendering pipeline.
    329 ///
    330 /// The request is guaranteed to be notified once and only once, even if the transaction
    331 /// is dropped before the requested check-point.
    332 pub struct NotificationRequest {
    333    handler: Option<Box<dyn NotificationHandler>>,
    334    when: Checkpoint,
    335 }
    336 
    337 impl NotificationRequest {
    338    /// Constructor.
    339    pub fn new(when: Checkpoint, handler: Box<dyn NotificationHandler>) -> Self {
    340        NotificationRequest {
    341            handler: Some(handler),
    342            when,
    343        }
    344    }
    345 
    346    /// The specified stage at which point the handler should be notified.
    347    pub fn when(&self) -> Checkpoint { self.when }
    348 
    349    /// Called by WebRender at specified stages to notify the registered handler.
    350    pub fn notify(mut self) {
    351        if let Some(handler) = self.handler.take() {
    352            handler.notify(self.when);
    353        }
    354    }
    355 }
    356 
    357 /// An object that can perform hit-testing without doing synchronous queries to
    358 /// the RenderBackendThread.
    359 pub trait ApiHitTester: Send + Sync {
    360    /// Does a hit test on display items in the specified document, at the given
    361    /// point. The vector of hit results will contain all display items that match,
    362    /// ordered from front to back.
    363    fn hit_test(&self, point: WorldPoint) -> HitTestResult;
    364 }
    365 
    366 /// A hit tester requested to the render backend thread but not necessarily ready yet.
    367 ///
    368 /// The request should be resolved as late as possible to reduce the likelihood of blocking.
    369 pub struct HitTesterRequest {
    370    #[doc(hidden)]
    371    pub rx: Receiver<Arc<dyn ApiHitTester>>,
    372 }
    373 
    374 impl HitTesterRequest {
    375    /// Block until the hit tester is available and return it, consuming teh request.
    376    pub fn resolve(self) -> Arc<dyn ApiHitTester> {
    377        self.rx.recv().unwrap()
    378    }
    379 }
    380 
    381 /// Describe an item that matched a hit-test query.
    382 #[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
    383 pub struct HitTestResultItem {
    384    /// The pipeline that the display item that was hit belongs to.
    385    pub pipeline: PipelineId,
    386 
    387    /// The tag of the hit display item.
    388    pub tag: ItemTag,
    389 
    390    /// The animation id from the stacking context.
    391    pub animation_id: u64,
    392 }
    393 
    394 /// Returned by `RenderApi::hit_test`.
    395 #[derive(Clone, Debug, Default, Deserialize, Serialize)]
    396 pub struct HitTestResult {
    397    /// List of items that are match the hit-test query.
    398    pub items: Vec<HitTestResultItem>,
    399 }
    400 
    401 impl Drop for NotificationRequest {
    402    fn drop(&mut self) {
    403        if let Some(ref mut handler) = self.handler {
    404            handler.notify(Checkpoint::TransactionDropped);
    405        }
    406    }
    407 }
    408 
    409 // This Clone impl yields an "empty" request because we don't want the requests
    410 // to be notified twice so the request is owned by only one of the API messages
    411 // (the original one) after the clone.
    412 // This works in practice because the notifications requests are used for
    413 // synchronization so we don't need to include them in the recording mechanism
    414 // in wrench that clones the messages.
    415 impl Clone for NotificationRequest {
    416    fn clone(&self) -> Self {
    417        NotificationRequest {
    418            when: self.when,
    419            handler: None,
    420        }
    421    }
    422 }
    423 
    424 
    425 /// A key to identify an animated property binding.
    426 #[repr(C)]
    427 #[derive(Clone, Copy, Debug, Default, Deserialize, MallocSizeOf, PartialEq, Serialize, Eq, Hash, PeekPoke)]
    428 pub struct PropertyBindingId {
    429    pub namespace: IdNamespace,
    430    pub uid: u32,
    431 }
    432 
    433 impl PropertyBindingId {
    434    /// Constructor.
    435    pub fn new(value: u64) -> Self {
    436        PropertyBindingId {
    437            namespace: IdNamespace((value >> 32) as u32),
    438            uid: value as u32,
    439        }
    440    }
    441 
    442    /// Decompose the ID back into the raw integer.
    443    pub fn to_u64(&self) -> u64 {
    444        ((self.namespace.0 as u64) << 32) | self.uid as u64
    445    }
    446 }
    447 
    448 /// A unique key that is used for connecting animated property
    449 /// values to bindings in the display list.
    450 #[repr(C)]
    451 #[derive(Clone, Copy, Debug, Default, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
    452 pub struct PropertyBindingKey<T> {
    453    ///
    454    pub id: PropertyBindingId,
    455    #[doc(hidden)]
    456    pub _phantom: PhantomData<T>,
    457 }
    458 
    459 /// Construct a property value from a given key and value.
    460 impl<T: Copy> PropertyBindingKey<T> {
    461    ///
    462    pub fn with(self, value: T) -> PropertyValue<T> {
    463        PropertyValue { key: self, value }
    464    }
    465 }
    466 
    467 impl<T> Into<u64> for PropertyBindingKey<T> {
    468    fn into(self) -> u64 {
    469        self.id.to_u64()
    470    }
    471 }
    472 
    473 impl<T> PropertyBindingKey<T> {
    474    /// Constructor.
    475    pub fn new(value: u64) -> Self {
    476        PropertyBindingKey {
    477            id: PropertyBindingId::new(value),
    478            _phantom: PhantomData,
    479        }
    480    }
    481 }
    482 
    483 /// A binding property can either be a specific value
    484 /// (the normal, non-animated case) or point to a binding location
    485 /// to fetch the current value from.
    486 /// Note that Binding has also a non-animated value, the value is
    487 /// used for the case where the animation is still in-delay phase
    488 /// (i.e. the animation doesn't produce any animation values).
    489 #[repr(C)]
    490 #[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
    491 pub enum PropertyBinding<T> {
    492    /// Non-animated value.
    493    Value(T),
    494    /// Animated binding.
    495    Binding(PropertyBindingKey<T>, T),
    496 }
    497 
    498 impl<T: Default> Default for PropertyBinding<T> {
    499    fn default() -> Self {
    500        PropertyBinding::Value(Default::default())
    501    }
    502 }
    503 
    504 impl<T> From<T> for PropertyBinding<T> {
    505    fn from(value: T) -> PropertyBinding<T> {
    506        PropertyBinding::Value(value)
    507    }
    508 }
    509 
    510 impl From<PropertyBindingKey<ColorF>> for PropertyBindingKey<ColorU> {
    511    fn from(key: PropertyBindingKey<ColorF>) -> PropertyBindingKey<ColorU> {
    512        PropertyBindingKey {
    513            id: key.id,
    514            _phantom: PhantomData,
    515        }
    516    }
    517 }
    518 
    519 impl From<PropertyBindingKey<ColorU>> for PropertyBindingKey<ColorF> {
    520    fn from(key: PropertyBindingKey<ColorU>) -> PropertyBindingKey<ColorF> {
    521        PropertyBindingKey {
    522            id: key.id,
    523            _phantom: PhantomData,
    524        }
    525    }
    526 }
    527 
    528 impl From<PropertyBinding<ColorF>> for PropertyBinding<ColorU> {
    529    fn from(value: PropertyBinding<ColorF>) -> PropertyBinding<ColorU> {
    530        match value {
    531            PropertyBinding::Value(value) => PropertyBinding::Value(value.into()),
    532            PropertyBinding::Binding(k, v) => {
    533                PropertyBinding::Binding(k.into(), v.into())
    534            }
    535        }
    536    }
    537 }
    538 
    539 impl From<PropertyBinding<ColorU>> for PropertyBinding<ColorF> {
    540    fn from(value: PropertyBinding<ColorU>) -> PropertyBinding<ColorF> {
    541        match value {
    542            PropertyBinding::Value(value) => PropertyBinding::Value(value.into()),
    543            PropertyBinding::Binding(k, v) => {
    544                PropertyBinding::Binding(k.into(), v.into())
    545            }
    546        }
    547    }
    548 }
    549 
    550 /// The current value of an animated property. This is
    551 /// supplied by the calling code.
    552 #[derive(Clone, Copy, Debug, Deserialize, Serialize, PartialEq)]
    553 pub struct PropertyValue<T> {
    554    ///
    555    pub key: PropertyBindingKey<T>,
    556    ///
    557    pub value: T,
    558 }
    559 
    560 /// When using `generate_frame()`, a list of `PropertyValue` structures
    561 /// can optionally be supplied to provide the current value of any
    562 /// animated properties.
    563 #[derive(Clone, Deserialize, Serialize, Debug, PartialEq, Default)]
    564 pub struct DynamicProperties {
    565    /// transform list
    566    pub transforms: Vec<PropertyValue<LayoutTransform>>,
    567    /// opacity
    568    pub floats: Vec<PropertyValue<f32>>,
    569    /// background color
    570    pub colors: Vec<PropertyValue<ColorF>>,
    571 }
    572 
    573 impl DynamicProperties {
    574    /// Extend the properties.
    575    pub fn extend(&mut self, other: Self) {
    576        self.transforms.extend(other.transforms);
    577        self.floats.extend(other.floats);
    578        self.colors.extend(other.colors);
    579    }
    580 }
    581 
    582 /// A C function that takes a pointer to a heap allocation and returns its size.
    583 ///
    584 /// This is borrowed from the malloc_size_of crate, upon which we want to avoid
    585 /// a dependency from WebRender.
    586 pub type VoidPtrToSizeFn = unsafe extern "C" fn(ptr: *const c_void) -> usize;
    587 
    588 /// A configuration option that can be changed at runtime.
    589 ///
    590 /// # Adding a new configuration option
    591 ///
    592 ///  - Add a new enum variant here.
    593 ///  - Add the entry in WR_BOOL_PARAMETER_LIST in gfxPlatform.cpp.
    594 ///  - React to the parameter change anywhere in WebRender where a SetParam message is received.
    595 #[derive(Copy, Clone, Debug, PartialEq)]
    596 pub enum Parameter {
    597    Bool(BoolParameter, bool),
    598    Int(IntParameter, i32),
    599    Float(FloatParameter, f32),
    600 }
    601 
    602 /// Boolean configuration option.
    603 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
    604 #[repr(u32)]
    605 pub enum BoolParameter {
    606    PboUploads = 0,
    607    Multithreading = 1,
    608    BatchedUploads = 2,
    609    DrawCallsForTextureCopy = 3,
    610 }
    611 
    612 /// Integer configuration option.
    613 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
    614 #[repr(u32)]
    615 pub enum IntParameter {
    616    BatchedUploadThreshold = 0,
    617 }
    618 
    619 /// Floating point configuration option.
    620 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
    621 #[repr(u32)]
    622 pub enum FloatParameter {
    623    /// The minimum time for the CPU portion of a frame to be considered slow
    624    SlowCpuFrameThreshold = 0,
    625 }
    626 
    627 /// Flags to track why we are rendering.
    628 #[repr(C)]
    629 #[derive(Copy, PartialEq, Eq, Clone, PartialOrd, Ord, Hash, Default, Deserialize, MallocSizeOf, Serialize)]
    630 pub struct RenderReasons(u32);
    631 
    632 bitflags! {
    633    impl RenderReasons: u32 {
    634        /// Equivalent of empty() for the C++ side.
    635        const NONE                          = 0;
    636        const SCENE                         = 1 << 0;
    637        const ANIMATED_PROPERTY             = 1 << 1;
    638        const RESOURCE_UPDATE               = 1 << 2;
    639        const ASYNC_IMAGE                   = 1 << 3;
    640        const CLEAR_RESOURCES               = 1 << 4;
    641        const APZ                           = 1 << 5;
    642        /// Window resize
    643        const RESIZE                        = 1 << 6;
    644        /// Various widget-related reasons
    645        const WIDGET                        = 1 << 7;
    646        /// See Frame::must_be_drawn
    647        const TEXTURE_CACHE_FLUSH           = 1 << 8;
    648        const SNAPSHOT                      = 1 << 9;
    649        const POST_RESOURCE_UPDATES_HOOK    = 1 << 10;
    650        const CONFIG_CHANGE                 = 1 << 11;
    651        const CONTENT_SYNC                  = 1 << 12;
    652        const FLUSH                         = 1 << 13;
    653        const TESTING                       = 1 << 14;
    654        const OTHER                         = 1 << 15;
    655        /// Vsync isn't actually "why" we render but it can be useful
    656        /// to see which frames were driven by the vsync scheduler so
    657        /// we store a bit for it.
    658        const VSYNC                         = 1 << 16;
    659        const SKIPPED_COMPOSITE             = 1 << 17;
    660        /// Gecko does some special things when it starts observing vsync
    661        /// so it can be useful to know what frames are associated with it.
    662        const START_OBSERVING_VSYNC         = 1 << 18;
    663        const ASYNC_IMAGE_COMPOSITE_UNTIL   = 1 << 19;
    664    }
    665 }
    666 
    667 impl core::fmt::Debug for RenderReasons {
    668    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
    669        if self.is_empty() {
    670            write!(f, "{:#x}", Self::empty().bits())
    671        } else {
    672            bitflags::parser::to_writer(self, f)
    673        }
    674    }
    675 }
    676 
    677 impl RenderReasons {
    678    pub const NUM_BITS: u32 = 17;
    679 }
    680 
    681 /// Flags to enable/disable various builtin debugging tools.
    682 #[repr(C)]
    683 #[derive(Copy, PartialEq, Eq, Clone, PartialOrd, Ord, Hash, Default, Deserialize, MallocSizeOf, Serialize)]
    684 pub struct DebugFlags(u64);
    685 
    686 bitflags! {
    687    impl DebugFlags: u64 {
    688        /// Display the frame profiler on screen.
    689        const PROFILER_DBG          = 1 << 0;
    690        /// Display intermediate render targets on screen.
    691        const RENDER_TARGET_DBG     = 1 << 1;
    692        /// Display all texture cache pages on screen.
    693        const TEXTURE_CACHE_DBG     = 1 << 2;
    694        /// Display GPU timing results.
    695        const GPU_TIME_QUERIES      = 1 << 3;
    696        /// Query the number of pixels that pass the depth test divided and show it
    697        /// in the profiler as a percentage of the number of pixels in the screen
    698        /// (window width times height).
    699        const GPU_SAMPLE_QUERIES    = 1 << 4;
    700        /// Render each quad with their own draw call.
    701        ///
    702        /// Terrible for performance but can help with understanding the drawing
    703        /// order when inspecting renderdoc or apitrace recordings.
    704        const DISABLE_BATCHING      = 1 << 5;
    705        /// Display the pipeline epochs.
    706        const EPOCHS                = 1 << 6;
    707        /// Print driver messages to stdout.
    708        const ECHO_DRIVER_MESSAGES  = 1 << 7;
    709        /// Show an overlay displaying overdraw amount.
    710        const SHOW_OVERDRAW         = 1 << 8;
    711        /// Display the contents of GPU cache.
    712        const GPU_CACHE_DBG         = 1 << 9;
    713        /// Clear evicted parts of the texture cache for debugging purposes.
    714        const TEXTURE_CACHE_DBG_CLEAR_EVICTED = 1 << 10;
    715        /// Show picture caching debug overlay
    716        const PICTURE_CACHING_DBG   = 1 << 11;
    717        /// Draw a zoom widget showing part of the framebuffer zoomed in.
    718        const ZOOM_DBG = 1 << 13;
    719        /// Scale the debug renderer down for a smaller screen. This will disrupt
    720        /// any mapping between debug display items and page content, so shouldn't
    721        /// be used with overlays like the picture caching or primitive display.
    722        const SMALL_SCREEN = 1 << 14;
    723        /// Disable various bits of the WebRender pipeline, to help narrow
    724        /// down where slowness might be coming from.
    725        const DISABLE_OPAQUE_PASS = 1 << 15;
    726        ///
    727        const DISABLE_ALPHA_PASS = 1 << 16;
    728        ///
    729        const DISABLE_CLIP_MASKS = 1 << 17;
    730        ///
    731        const DISABLE_TEXT_PRIMS = 1 << 18;
    732        ///
    733        const DISABLE_GRADIENT_PRIMS = 1 << 19;
    734        ///
    735        const OBSCURE_IMAGES = 1 << 20;
    736        /// Taint the transparent area of the glyphs with a random opacity to easily
    737        /// see when glyphs are re-rasterized.
    738        const GLYPH_FLASHING = 1 << 21;
    739        /// The profiler only displays information that is out of the ordinary.
    740        const SMART_PROFILER        = 1 << 22;
    741        /// If set, dump picture cache invalidation debug to console.
    742        const INVALIDATION_DBG = 1 << 23;
    743        /// Collect and dump profiler statistics to captures.
    744        const PROFILER_CAPTURE = 1 << 25;
    745        /// Invalidate picture tiles every frames (useful when inspecting GPU work in external tools).
    746        const FORCE_PICTURE_INVALIDATION = 1 << 26;
    747        /// Display window visibility on screen.
    748        const WINDOW_VISIBILITY_DBG     = 1 << 27;
    749        /// Render large blobs with at a smaller size (incorrectly). This is a temporary workaround for
    750        /// fuzzing.
    751        const RESTRICT_BLOB_SIZE        = 1 << 28;
    752        /// Enable surface promotion logging.
    753        const SURFACE_PROMOTION_LOGGING = 1 << 29;
    754        /// Show picture caching debug overlay.
    755        const PICTURE_BORDERS           = 1 << 30;
    756        /// Panic when a attempting to display a missing stacking context snapshot.
    757        const MISSING_SNAPSHOT_PANIC    = (1 as u64) << 31; // need "as u32" until we have cbindgen#556
    758        /// Panic when a attempting to display a missing stacking context snapshot.
    759        const MISSING_SNAPSHOT_PINK     = (1 as u64) << 32;
    760        /// Highlight backdrop filters
    761        const HIGHLIGHT_BACKDROP_FILTERS = (1 as u64) << 33;
    762        /// Show external composite border rects in debug overlay.
    763        /// TODO: Add native compositor support
    764        const EXTERNAL_COMPOSITE_BORDERS = (1 as u64) << 34;
    765    }
    766 }
    767 
    768 impl core::fmt::Debug for DebugFlags {
    769    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
    770        if self.is_empty() {
    771            write!(f, "{:#x}", Self::empty().bits())
    772        } else {
    773            bitflags::parser::to_writer(self, f)
    774        }
    775    }
    776 }
    777 
    778 /// Information specific to a primitive type that
    779 /// uniquely identifies a primitive template by key.
    780 #[derive(Debug, Clone, Eq, MallocSizeOf, PartialEq, Hash, Serialize, Deserialize)]
    781 pub enum PrimitiveKeyKind {
    782    ///
    783    Rectangle {
    784        ///
    785        color: PropertyBinding<ColorU>,
    786    },
    787 }
    788 
    789 ///
    790 #[derive(Clone, Copy, Debug)]
    791 pub enum ScrollLocation {
    792    /// Scroll by a certain amount.
    793    Delta(LayoutVector2D),
    794    /// Scroll to very top of element.
    795    Start,
    796    /// Scroll to very bottom of element.
    797    End,
    798 }
    799 
    800 /// Crash annotations included in crash reports.
    801 #[repr(C)]
    802 #[derive(Clone, Copy)]
    803 pub enum CrashAnnotation {
    804    CompileShader = 0,
    805    DrawShader = 1,
    806    FontFile = 2,
    807 }
    808 
    809 /// Handler to expose support for annotating crash reports.
    810 pub trait CrashAnnotator : Send {
    811    fn set(&self, annotation: CrashAnnotation, value: &std::ffi::CStr);
    812    fn clear(&self, annotation: CrashAnnotation);
    813    fn box_clone(&self) -> Box<dyn CrashAnnotator>;
    814 }
    815 
    816 impl Clone for Box<dyn CrashAnnotator> {
    817    fn clone(&self) -> Box<dyn CrashAnnotator> {
    818        self.box_clone()
    819    }
    820 }
    821 
    822 /// Guard to add a crash annotation at creation, and clear it at destruction.
    823 pub struct CrashAnnotatorGuard<'a> {
    824    annotator: &'a Option<Box<dyn CrashAnnotator>>,
    825    annotation: CrashAnnotation,
    826 }
    827 
    828 impl<'a> CrashAnnotatorGuard<'a> {
    829    pub fn new(
    830        annotator: &'a Option<Box<dyn CrashAnnotator>>,
    831        annotation: CrashAnnotation,
    832        value: &std::ffi::CStr,
    833    ) -> Self {
    834        if let Some(ref annotator) = annotator {
    835            annotator.set(annotation, value);
    836        }
    837        Self {
    838            annotator,
    839            annotation,
    840        }
    841    }
    842 }
    843 
    844 impl<'a> Drop for CrashAnnotatorGuard<'a> {
    845    fn drop(&mut self) {
    846        if let Some(ref annotator) = self.annotator {
    847            annotator.clear(self.annotation);
    848        }
    849    }
    850 }
    851 
    852 /// A little bit of extra information to make memory reports more useful
    853 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
    854 #[cfg_attr(feature = "serialize", derive(Serialize))]
    855 #[cfg_attr(feature = "deserialize", derive(Deserialize))]
    856 pub enum TextureCacheCategory {
    857    Atlas,
    858    Standalone,
    859    PictureTile,
    860    RenderTarget,
    861 }
    862 
    863 /// For debugging purposes
    864 #[derive(Clone, Debug)]
    865 #[cfg_attr(feature = "serialize", derive(Serialize))]
    866 #[cfg_attr(feature = "deserialize", derive(Deserialize))]
    867 pub enum RenderCommandInfo {
    868    RenderTarget { kind: String, size: DeviceIntSize },
    869    DrawCall { shader: String, instances: u32 },
    870 }