zng_webrender_api/
lib.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//! 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
27pub extern crate crossbeam_channel;
28pub extern crate euclid;
29
30extern crate app_units;
31#[macro_use]
32extern crate bitflags;
33extern crate byteorder;
34#[cfg(feature = "nightly")]
35extern crate core;
36#[macro_use]
37extern crate malloc_size_of_derive;
38extern crate serde;
39#[macro_use]
40extern crate serde_derive;
41
42extern crate malloc_size_of;
43extern crate peek_poke;
44
45pub mod channel;
46mod color;
47#[cfg(feature = "debugger")]
48pub mod debugger;
49mod display_item;
50mod display_item_cache;
51mod display_list;
52mod font;
53mod gradient_builder;
54mod image;
55mod tile_pool;
56pub mod units;
57
58pub use crate::color::*;
59pub use crate::display_item::*;
60pub use crate::display_item_cache::DisplayItemCache;
61pub use crate::display_list::*;
62pub use crate::font::*;
63pub use crate::gradient_builder::*;
64pub use crate::image::*;
65pub use crate::tile_pool::*;
66
67use crate::units::*;
68use crate::channel::Receiver;
69use std::marker::PhantomData;
70use std::sync::Arc;
71use std::os::raw::c_void;
72use peek_poke::PeekPoke;
73
74/// Defined here for cbindgen
75pub const MAX_RENDER_TASK_SIZE: i32 = 16384;
76
77/// Width and height in device pixels of image tiles.
78pub 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)]
83pub 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
91impl 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)]
107pub struct Epoch(pub u32);
108
109impl 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)]
122pub struct IdNamespace(pub u32);
123
124impl 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)]
135pub struct DocumentId {
136    ///
137    pub namespace_id: IdNamespace,
138    ///
139    pub id: u32,
140}
141
142impl 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.
159pub 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)]
165pub struct PipelineId(pub PipelineSourceId, pub u32);
166
167impl Default for PipelineId {
168    fn default() -> Self {
169        PipelineId::dummy()
170    }
171}
172
173impl 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)]
184pub struct FramePublishId(pub u64);
185
186impl 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
206impl 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)]
215pub struct ExternalEvent {
216    raw: usize,
217}
218
219unsafe impl Send for ExternalEvent {}
220
221impl 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
232pub type APZScrollGeneration = u64;
233#[repr(C)]
234#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize, Default)]
235pub 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)]
246pub enum HasScrollLinkedEffect {
247    Yes,
248    #[default]
249    No,
250}
251
252#[repr(C)]
253pub 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)]
270pub 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`.
281pub 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)]
306pub 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.
322pub 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.
332pub struct NotificationRequest {
333    handler: Option<Box<dyn NotificationHandler>>,
334    when: Checkpoint,
335}
336
337impl 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.
359pub 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.
369pub struct HitTesterRequest {
370    #[doc(hidden)]
371    pub rx: Receiver<Arc<dyn ApiHitTester>>,
372}
373
374impl 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)]
383pub 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)]
396pub struct HitTestResult {
397    /// List of items that are match the hit-test query.
398    pub items: Vec<HitTestResultItem>,
399}
400
401impl 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.
415impl 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)]
428pub struct PropertyBindingId {
429    pub namespace: IdNamespace,
430    pub uid: u32,
431}
432
433impl 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)]
452pub 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.
460impl<T: Copy> PropertyBindingKey<T> {
461    ///
462    pub fn with(self, value: T) -> PropertyValue<T> {
463        PropertyValue { key: self, value }
464    }
465}
466
467impl<T> Into<u64> for PropertyBindingKey<T> {
468    fn into(self) -> u64 {
469        self.id.to_u64()
470    }
471}
472
473impl<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)]
491pub enum PropertyBinding<T> {
492    /// Non-animated value.
493    Value(T),
494    /// Animated binding.
495    Binding(PropertyBindingKey<T>, T),
496}
497
498impl<T: Default> Default for PropertyBinding<T> {
499    fn default() -> Self {
500        PropertyBinding::Value(Default::default())
501    }
502}
503
504impl<T> From<T> for PropertyBinding<T> {
505    fn from(value: T) -> PropertyBinding<T> {
506        PropertyBinding::Value(value)
507    }
508}
509
510impl 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
519impl 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
528impl 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
539impl 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)]
553pub 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)]
564pub 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
573impl 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.
586pub 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)]
596pub 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)]
605pub 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)]
615pub enum IntParameter {
616    BatchedUploadThreshold = 0,
617}
618
619/// Floating point configuration option.
620#[derive(Copy, Clone, Debug, PartialEq, Eq)]
621#[repr(u32)]
622pub 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)]
630pub struct RenderReasons(u32);
631
632bitflags! {
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
667impl 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
677impl 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)]
684pub struct DebugFlags(u64);
685
686bitflags! {
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
768impl 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)]
781pub enum PrimitiveKeyKind {
782    /// Clear an existing rect, used for special effects on some platforms.
783    Clear,
784    ///
785    Rectangle {
786        ///
787        color: PropertyBinding<ColorU>,
788    },
789}
790
791///
792#[derive(Clone, Copy, Debug)]
793pub enum ScrollLocation {
794    /// Scroll by a certain amount.
795    Delta(LayoutVector2D),
796    /// Scroll to very top of element.
797    Start,
798    /// Scroll to very bottom of element.
799    End,
800}
801
802/// Crash annotations included in crash reports.
803#[repr(C)]
804#[derive(Clone, Copy)]
805pub enum CrashAnnotation {
806    CompileShader = 0,
807    DrawShader = 1,
808}
809
810/// Handler to expose support for annotating crash reports.
811pub trait CrashAnnotator : Send {
812    fn set(&self, annotation: CrashAnnotation, value: &std::ffi::CStr);
813    fn clear(&self, annotation: CrashAnnotation);
814    fn box_clone(&self) -> Box<dyn CrashAnnotator>;
815}
816
817impl Clone for Box<dyn CrashAnnotator> {
818    fn clone(&self) -> Box<dyn CrashAnnotator> {
819        self.box_clone()
820    }
821}
822
823/// Guard to add a crash annotation at creation, and clear it at destruction.
824pub struct CrashAnnotatorGuard<'a> {
825    annotator: &'a Option<Box<dyn CrashAnnotator>>,
826    annotation: CrashAnnotation,
827}
828
829impl<'a> CrashAnnotatorGuard<'a> {
830    pub fn new(
831        annotator: &'a Option<Box<dyn CrashAnnotator>>,
832        annotation: CrashAnnotation,
833        value: &std::ffi::CStr,
834    ) -> Self {
835        if let Some(ref annotator) = annotator {
836            annotator.set(annotation, value);
837        }
838        Self {
839            annotator,
840            annotation,
841        }
842    }
843}
844
845impl<'a> Drop for CrashAnnotatorGuard<'a> {
846    fn drop(&mut self) {
847        if let Some(ref annotator) = self.annotator {
848            annotator.clear(self.annotation);
849        }
850    }
851}
852
853/// A little bit of extra information to make memory reports more useful
854#[derive(Copy, Clone, Debug, Eq, PartialEq)]
855#[cfg_attr(feature = "serialize", derive(Serialize))]
856#[cfg_attr(feature = "deserialize", derive(Deserialize))]
857pub enum TextureCacheCategory {
858    Atlas,
859    Standalone,
860    PictureTile,
861    RenderTarget,
862}