1use api::{ColorF, DocumentId, ExternalImageId, PrimitiveFlags, Parameter, RenderReasons};
6use api::{ImageFormat, NotificationRequest, Shadow, FilterOpGraphPictureBufferId, FilterOpGraphPictureReference, FilterOpGraphNode, FilterOp, ImageBufferKind};
7use api::FramePublishId;
8use api::units::*;
9use crate::render_api::DebugCommand;
10use crate::composite::NativeSurfaceOperation;
11use crate::device::TextureFilter;
12use crate::renderer::{FullFrameStats, PipelineInfo};
13use crate::gpu_cache::GpuCacheUpdateList;
14use crate::gpu_types::BlurEdgeMode;
15use crate::frame_builder::Frame;
16use crate::profiler::TransactionProfile;
17use crate::spatial_tree::SpatialNodeIndex;
18use crate::prim_store::PrimitiveInstanceIndex;
19use crate::filterdata::FilterDataHandle;
20use rustc_hash::FxHasher;
21use plane_split::BspSplitter;
22use smallvec::SmallVec;
23use std::{usize, i32};
24use std::collections::{HashMap, HashSet};
25use std::f32;
26use std::hash::BuildHasherDefault;
27use std::path::PathBuf;
28use std::sync::Arc;
29use std::time::{UNIX_EPOCH, SystemTime};
30use peek_poke::PeekPoke;
31
32#[cfg(any(feature = "capture", feature = "replay"))]
33use crate::capture::CaptureConfig;
34#[cfg(feature = "capture")]
35use crate::capture::ExternalCaptureImage;
36#[cfg(feature = "replay")]
37use crate::capture::PlainExternalImage;
38
39pub use crate::frame_allocator::{FrameAllocator, FrameMemory};
40pub type FrameVec<T> = allocator_api2::vec::Vec<T, FrameAllocator>;
41pub fn size_of_frame_vec<T>(vec: &FrameVec<T>) -> usize {
42    vec.capacity() * std::mem::size_of::<T>()
43}
44
45pub type FastHashMap<K, V> = HashMap<K, V, BuildHasherDefault<FxHasher>>;
46pub type FastHashSet<K> = HashSet<K, BuildHasherDefault<FxHasher>>;
47
48#[derive(Copy, Clone, Hash, MallocSizeOf, PartialEq, PartialOrd, Debug, Eq, Ord, PeekPoke)]
49#[cfg_attr(feature = "capture", derive(Serialize))]
50#[cfg_attr(feature = "replay", derive(Deserialize))]
51pub struct FrameId(u64);
52
53impl FrameId {
54    pub fn first() -> Self {
62        FrameId(0)
63    }
64
65    pub fn as_u64(&self) -> u64 {
67        self.0
68    }
69
70    pub fn advance(&mut self) {
72        self.0 += 1;
73    }
74
75    pub const INVALID: FrameId = FrameId(0);
78}
79
80impl Default for FrameId {
81    fn default() -> Self {
82        FrameId::INVALID
83    }
84}
85
86impl ::std::ops::Add<u64> for FrameId {
87    type Output = Self;
88    fn add(self, other: u64) -> FrameId {
89        FrameId(self.0 + other)
90    }
91}
92
93impl ::std::ops::Sub<u64> for FrameId {
94    type Output = Self;
95    fn sub(self, other: u64) -> FrameId {
96        assert!(self.0 >= other, "Underflow subtracting FrameIds");
97        FrameId(self.0 - other)
98    }
99}
100
101#[derive(Copy, Clone, Debug, MallocSizeOf)]
109#[cfg_attr(feature = "capture", derive(Serialize))]
110#[cfg_attr(feature = "replay", derive(Deserialize))]
111pub struct FrameStamp {
112    id: FrameId,
113    time: SystemTime,
114    document_id: DocumentId,
115}
116
117impl Eq for FrameStamp {}
118
119impl PartialEq for FrameStamp {
120    fn eq(&self, other: &Self) -> bool {
121        debug_assert_eq!(self.document_id, other.document_id);
123        self.id == other.id
124    }
125}
126
127impl PartialOrd for FrameStamp {
128    fn partial_cmp(&self, other: &Self) -> Option<::std::cmp::Ordering> {
129        self.id.partial_cmp(&other.id)
130    }
131}
132
133impl FrameStamp {
134    pub fn frame_id(&self) -> FrameId {
136        self.id
137    }
138
139    pub fn time(&self) -> SystemTime {
141        self.time
142    }
143
144    pub fn document_id(&self) -> DocumentId {
146        self.document_id
147    }
148
149    pub fn is_valid(&self) -> bool {
150        debug_assert!((self.time != UNIX_EPOCH && self.id != FrameId(0) && self.document_id != DocumentId::INVALID) ||
152                      *self == Self::INVALID);
153        self.document_id != DocumentId::INVALID
154    }
155
156    pub fn first(document_id: DocumentId) -> Self {
158        FrameStamp {
159            id: FrameId::first(),
160            time: SystemTime::now(),
161            document_id,
162        }
163    }
164
165    pub fn advance(&mut self) {
167        self.id.advance();
168        self.time = SystemTime::now();
169    }
170
171    pub const INVALID: FrameStamp = FrameStamp {
173        id: FrameId(0),
174        time: UNIX_EPOCH,
175        document_id: DocumentId::INVALID,
176    };
177}
178
179#[derive(Copy, Clone, Debug)]
181#[cfg_attr(feature = "capture", derive(Serialize))]
182pub struct PlaneSplitAnchor {
183    pub spatial_node_index: SpatialNodeIndex,
184    pub instance_index: PrimitiveInstanceIndex,
185}
186
187impl PlaneSplitAnchor {
188    pub fn new(
189        spatial_node_index: SpatialNodeIndex,
190        instance_index: PrimitiveInstanceIndex,
191    ) -> Self {
192        PlaneSplitAnchor {
193            spatial_node_index,
194            instance_index,
195        }
196    }
197}
198
199impl Default for PlaneSplitAnchor {
200    fn default() -> Self {
201        PlaneSplitAnchor {
202            spatial_node_index: SpatialNodeIndex::INVALID,
203            instance_index: PrimitiveInstanceIndex(!0),
204        }
205    }
206}
207
208pub type PlaneSplitter = BspSplitter<PlaneSplitAnchor>;
210
211#[derive(Debug, Copy, Clone)]
213#[cfg_attr(feature = "capture", derive(Serialize))]
214pub struct PlaneSplitterIndex(pub usize);
215
216const OPACITY_EPSILON: f32 = 0.001;
218
219#[derive(Clone, Copy, Debug)]
220#[cfg_attr(feature = "capture", derive(Serialize))]
221#[cfg_attr(feature = "replay", derive(Deserialize))]
222pub struct FilterGraphPictureReference {
223    pub buffer_id: FilterOpGraphPictureBufferId,
227    pub subregion: LayoutRect,
230    pub offset: LayoutVector2D,
237    pub inflate: i16,
239    pub source_padding: LayoutRect,
243    pub target_padding: LayoutRect,
249}
250
251impl From<FilterOpGraphPictureReference> for FilterGraphPictureReference {
252    fn from(pic: FilterOpGraphPictureReference) -> Self {
253        FilterGraphPictureReference{
254            buffer_id: pic.buffer_id,
255            subregion: LayoutRect::zero(),
257            offset: LayoutVector2D::zero(),
258            inflate: 0,
259            source_padding: LayoutRect::zero(),
260            target_padding: LayoutRect::zero(),
261        }
262    }
263}
264
265pub const SVGFE_CONVOLVE_DIAMETER_LIMIT: usize = 5;
266pub const SVGFE_CONVOLVE_VALUES_LIMIT: usize = SVGFE_CONVOLVE_DIAMETER_LIMIT *
267    SVGFE_CONVOLVE_DIAMETER_LIMIT;
268
269#[derive(Clone, Debug)]
270#[cfg_attr(feature = "capture", derive(Serialize))]
271#[cfg_attr(feature = "replay", derive(Deserialize))]
272pub enum FilterGraphOp {
273    SVGFESourceGraphic,
279    SVGFESourceAlpha,
285    SVGFEIdentity,
291    SVGFEOpacity{valuebinding: api::PropertyBinding<f32>, value: f32},
297    SVGFEToAlpha,
300    SVGFEBlendDarken,
306    SVGFEBlendLighten,
312    SVGFEBlendMultiply,
318    SVGFEBlendNormal,
324    SVGFEBlendScreen,
330    SVGFEBlendOverlay,
336    SVGFEBlendColorDodge,
342    SVGFEBlendColorBurn,
348    SVGFEBlendHardLight,
354    SVGFEBlendSoftLight,
360    SVGFEBlendDifference,
366    SVGFEBlendExclusion,
372    SVGFEBlendHue,
378    SVGFEBlendSaturation,
384    SVGFEBlendColor,
390    SVGFEBlendLuminosity,
396    SVGFEColorMatrix{values: [f32; 20]},
403    SVGFEComponentTransfer,
410    SVGFEComponentTransferInterned{handle: FilterDataHandle, creates_pixels: bool},
415    SVGFECompositeArithmetic{k1: f32, k2: f32, k3: f32, k4: f32},
422    SVGFECompositeATop,
429    SVGFECompositeIn,
436    SVGFECompositeLighter,
443    SVGFECompositeOut,
450    SVGFECompositeOver,
457    SVGFECompositeXOR,
464    SVGFEConvolveMatrixEdgeModeDuplicate{order_x: i32, order_y: i32,
473        kernel: [f32; SVGFE_CONVOLVE_VALUES_LIMIT], divisor: f32, bias: f32,
474        target_x: i32, target_y: i32, kernel_unit_length_x: f32,
475        kernel_unit_length_y: f32, preserve_alpha: i32},
476    SVGFEConvolveMatrixEdgeModeNone{order_x: i32, order_y: i32,
485        kernel: [f32; SVGFE_CONVOLVE_VALUES_LIMIT], divisor: f32, bias: f32,
486        target_x: i32, target_y: i32, kernel_unit_length_x: f32,
487        kernel_unit_length_y: f32, preserve_alpha: i32},
488    SVGFEConvolveMatrixEdgeModeWrap{order_x: i32, order_y: i32,
497        kernel: [f32; SVGFE_CONVOLVE_VALUES_LIMIT], divisor: f32, bias: f32,
498        target_x: i32, target_y: i32, kernel_unit_length_x: f32,
499        kernel_unit_length_y: f32, preserve_alpha: i32},
500    SVGFEDiffuseLightingDistant{surface_scale: f32, diffuse_constant: f32,
509        kernel_unit_length_x: f32, kernel_unit_length_y: f32, azimuth: f32,
510        elevation: f32},
511    SVGFEDiffuseLightingPoint{surface_scale: f32, diffuse_constant: f32,
520        kernel_unit_length_x: f32, kernel_unit_length_y: f32, x: f32, y: f32,
521        z: f32},
522    SVGFEDiffuseLightingSpot{surface_scale: f32, diffuse_constant: f32,
533        kernel_unit_length_x: f32, kernel_unit_length_y: f32, x: f32, y: f32,
534        z: f32, points_at_x: f32, points_at_y: f32, points_at_z: f32,
535        cone_exponent: f32, limiting_cone_angle: f32},
536    SVGFEDisplacementMap{scale: f32, x_channel_selector: u32,
543        y_channel_selector: u32},
544    SVGFEDropShadow{color: ColorF, dx: f32, dy: f32, std_deviation_x: f32,
552        std_deviation_y: f32},
553    SVGFEFlood{color: ColorF},
559    SVGFEGaussianBlur{std_deviation_x: f32, std_deviation_y: f32},
565    SVGFEImage{sampling_filter: u32, matrix: [f32; 6]},
572    SVGFEMorphologyDilate{radius_x: f32, radius_y: f32},
579    SVGFEMorphologyErode{radius_x: f32, radius_y: f32},
586    SVGFESpecularLightingDistant{surface_scale: f32, specular_constant: f32,
595        specular_exponent: f32, kernel_unit_length_x: f32,
596        kernel_unit_length_y: f32, azimuth: f32, elevation: f32},
597    SVGFESpecularLightingPoint{surface_scale: f32, specular_constant: f32,
606        specular_exponent: f32, kernel_unit_length_x: f32,
607        kernel_unit_length_y: f32, x: f32, y: f32, z: f32},
608    SVGFESpecularLightingSpot{surface_scale: f32, specular_constant: f32,
619        specular_exponent: f32, kernel_unit_length_x: f32,
620        kernel_unit_length_y: f32, x: f32, y: f32, z: f32, points_at_x: f32,
621        points_at_y: f32, points_at_z: f32, cone_exponent: f32,
622        limiting_cone_angle: f32},
623    SVGFETile,
630    SVGFETurbulenceWithFractalNoiseWithNoStitching{base_frequency_x: f32,
638        base_frequency_y: f32, num_octaves: u32, seed: u32},
639    SVGFETurbulenceWithFractalNoiseWithStitching{base_frequency_x: f32,
647        base_frequency_y: f32, num_octaves: u32, seed: u32},
648    SVGFETurbulenceWithTurbulenceNoiseWithNoStitching{base_frequency_x: f32,
655        base_frequency_y: f32, num_octaves: u32, seed: u32},
656    SVGFETurbulenceWithTurbulenceNoiseWithStitching{base_frequency_x: f32,
663        base_frequency_y: f32, num_octaves: u32, seed: u32},
664}
665
666impl FilterGraphOp {
667    pub fn kind(&self) -> &'static str {
668        match *self {
669            FilterGraphOp::SVGFEBlendColor => "SVGFEBlendColor",
670            FilterGraphOp::SVGFEBlendColorBurn => "SVGFEBlendColorBurn",
671            FilterGraphOp::SVGFEBlendColorDodge => "SVGFEBlendColorDodge",
672            FilterGraphOp::SVGFEBlendDarken => "SVGFEBlendDarken",
673            FilterGraphOp::SVGFEBlendDifference => "SVGFEBlendDifference",
674            FilterGraphOp::SVGFEBlendExclusion => "SVGFEBlendExclusion",
675            FilterGraphOp::SVGFEBlendHardLight => "SVGFEBlendHardLight",
676            FilterGraphOp::SVGFEBlendHue => "SVGFEBlendHue",
677            FilterGraphOp::SVGFEBlendLighten => "SVGFEBlendLighten",
678            FilterGraphOp::SVGFEBlendLuminosity => "SVGFEBlendLuminosity",
679            FilterGraphOp::SVGFEBlendMultiply => "SVGFEBlendMultiply",
680            FilterGraphOp::SVGFEBlendNormal => "SVGFEBlendNormal",
681            FilterGraphOp::SVGFEBlendOverlay => "SVGFEBlendOverlay",
682            FilterGraphOp::SVGFEBlendSaturation => "SVGFEBlendSaturation",
683            FilterGraphOp::SVGFEBlendScreen => "SVGFEBlendScreen",
684            FilterGraphOp::SVGFEBlendSoftLight => "SVGFEBlendSoftLight",
685            FilterGraphOp::SVGFEColorMatrix{..} => "SVGFEColorMatrix",
686            FilterGraphOp::SVGFEComponentTransfer => "SVGFEComponentTransfer",
687            FilterGraphOp::SVGFEComponentTransferInterned{..} => "SVGFEComponentTransferInterned",
688            FilterGraphOp::SVGFECompositeArithmetic{..} => "SVGFECompositeArithmetic",
689            FilterGraphOp::SVGFECompositeATop => "SVGFECompositeATop",
690            FilterGraphOp::SVGFECompositeIn => "SVGFECompositeIn",
691            FilterGraphOp::SVGFECompositeLighter => "SVGFECompositeLighter",
692            FilterGraphOp::SVGFECompositeOut => "SVGFECompositeOut",
693            FilterGraphOp::SVGFECompositeOver => "SVGFECompositeOver",
694            FilterGraphOp::SVGFECompositeXOR => "SVGFECompositeXOR",
695            FilterGraphOp::SVGFEConvolveMatrixEdgeModeDuplicate{..} => "SVGFEConvolveMatrixEdgeModeDuplicate",
696            FilterGraphOp::SVGFEConvolveMatrixEdgeModeNone{..} => "SVGFEConvolveMatrixEdgeModeNone",
697            FilterGraphOp::SVGFEConvolveMatrixEdgeModeWrap{..} => "SVGFEConvolveMatrixEdgeModeWrap",
698            FilterGraphOp::SVGFEDiffuseLightingDistant{..} => "SVGFEDiffuseLightingDistant",
699            FilterGraphOp::SVGFEDiffuseLightingPoint{..} => "SVGFEDiffuseLightingPoint",
700            FilterGraphOp::SVGFEDiffuseLightingSpot{..} => "SVGFEDiffuseLightingSpot",
701            FilterGraphOp::SVGFEDisplacementMap{..} => "SVGFEDisplacementMap",
702            FilterGraphOp::SVGFEDropShadow{..} => "SVGFEDropShadow",
703            FilterGraphOp::SVGFEFlood{..} => "SVGFEFlood",
704            FilterGraphOp::SVGFEGaussianBlur{..} => "SVGFEGaussianBlur",
705            FilterGraphOp::SVGFEIdentity => "SVGFEIdentity",
706            FilterGraphOp::SVGFEImage{..} => "SVGFEImage",
707            FilterGraphOp::SVGFEMorphologyDilate{..} => "SVGFEMorphologyDilate",
708            FilterGraphOp::SVGFEMorphologyErode{..} => "SVGFEMorphologyErode",
709            FilterGraphOp::SVGFEOpacity{..} => "SVGFEOpacity",
710            FilterGraphOp::SVGFESourceAlpha => "SVGFESourceAlpha",
711            FilterGraphOp::SVGFESourceGraphic => "SVGFESourceGraphic",
712            FilterGraphOp::SVGFESpecularLightingDistant{..} => "SVGFESpecularLightingDistant",
713            FilterGraphOp::SVGFESpecularLightingPoint{..} => "SVGFESpecularLightingPoint",
714            FilterGraphOp::SVGFESpecularLightingSpot{..} => "SVGFESpecularLightingSpot",
715            FilterGraphOp::SVGFETile => "SVGFETile",
716            FilterGraphOp::SVGFEToAlpha => "SVGFEToAlpha",
717            FilterGraphOp::SVGFETurbulenceWithFractalNoiseWithNoStitching{..} => "SVGFETurbulenceWithFractalNoiseWithNoStitching",
718            FilterGraphOp::SVGFETurbulenceWithFractalNoiseWithStitching{..} => "SVGFETurbulenceWithFractalNoiseWithStitching",
719            FilterGraphOp::SVGFETurbulenceWithTurbulenceNoiseWithNoStitching{..} => "SVGFETurbulenceWithTurbulenceNoiseWithNoStitching",
720            FilterGraphOp::SVGFETurbulenceWithTurbulenceNoiseWithStitching{..} => "SVGFETurbulenceWithTurbulenceNoiseWithStitching",
721        }
722    }
723}
724
725#[derive(Clone, Debug)]
726#[cfg_attr(feature = "capture", derive(Serialize))]
727#[cfg_attr(feature = "replay", derive(Deserialize))]
728pub struct FilterGraphNode {
729    pub kept_by_optimizer: bool,
731    pub linear: bool,
735    pub inflate: i16,
738    pub inputs: Vec<FilterGraphPictureReference>,
741    pub subregion: LayoutRect,
743}
744
745impl From<FilterOpGraphNode> for FilterGraphNode {
746    fn from(node: FilterOpGraphNode) -> Self {
747        let mut inputs: Vec<FilterGraphPictureReference> = Vec::new();
748        if node.input.buffer_id != FilterOpGraphPictureBufferId::None {
749            inputs.push(node.input.into());
750        }
751        if node.input2.buffer_id != FilterOpGraphPictureBufferId::None {
752            inputs.push(node.input2.into());
753        }
754        FilterGraphNode{
757            linear: node.linear,
758            inputs,
759            subregion: node.subregion,
760            kept_by_optimizer: true,
762            inflate: 0,
763        }
764    }
765}
766
767
768#[derive(Clone, Debug)]
770#[cfg_attr(feature = "capture", derive(Serialize))]
771#[cfg_attr(feature = "replay", derive(Deserialize))]
772pub enum Filter {
773    Identity,
774    Blur {
775        width: f32,
776        height: f32,
777        should_inflate: bool,
778        edge_mode: BlurEdgeMode,
779    },
780    Brightness(f32),
781    Contrast(f32),
782    Grayscale(f32),
783    HueRotate(f32),
784    Invert(f32),
785    Opacity(api::PropertyBinding<f32>, f32),
786    Saturate(f32),
787    Sepia(f32),
788    DropShadows(SmallVec<[Shadow; 1]>),
789    ColorMatrix(Box<[f32; 20]>),
790    SrgbToLinear,
791    LinearToSrgb,
792    ComponentTransfer,
793    Flood(ColorF),
794    SVGGraphNode(FilterGraphNode, FilterGraphOp),
795}
796
797impl Filter {
798    pub fn is_visible(&self) -> bool {
799        match *self {
800            Filter::Identity |
801            Filter::Blur { .. } |
802            Filter::Brightness(..) |
803            Filter::Contrast(..) |
804            Filter::Grayscale(..) |
805            Filter::HueRotate(..) |
806            Filter::Invert(..) |
807            Filter::Saturate(..) |
808            Filter::Sepia(..) |
809            Filter::DropShadows(..) |
810            Filter::ColorMatrix(..) |
811            Filter::SrgbToLinear |
812            Filter::LinearToSrgb |
813            Filter::ComponentTransfer  => true,
814            Filter::Opacity(_, amount) => {
815                amount > OPACITY_EPSILON
816            },
817            Filter::Flood(color) => {
818                color.a > OPACITY_EPSILON
819            }
820            Filter::SVGGraphNode(..) => true,
821        }
822    }
823
824    pub fn is_noop(&self) -> bool {
825        match *self {
826            Filter::Identity => false, Filter::Blur { width, height, .. } => width == 0.0 && height == 0.0,
828            Filter::Brightness(amount) => amount == 1.0,
829            Filter::Contrast(amount) => amount == 1.0,
830            Filter::Grayscale(amount) => amount == 0.0,
831            Filter::HueRotate(amount) => amount == 0.0,
832            Filter::Invert(amount) => amount == 0.0,
833            Filter::Opacity(api::PropertyBinding::Value(amount), _) => amount >= 1.0,
834            Filter::Saturate(amount) => amount == 1.0,
835            Filter::Sepia(amount) => amount == 0.0,
836            Filter::DropShadows(ref shadows) => {
837                for shadow in shadows {
838                    if shadow.offset.x != 0.0 || shadow.offset.y != 0.0 || shadow.blur_radius != 0.0 {
839                        return false;
840                    }
841                }
842
843                true
844            }
845            Filter::ColorMatrix(ref matrix) => {
846                **matrix == [
847                    1.0, 0.0, 0.0, 0.0,
848                    0.0, 1.0, 0.0, 0.0,
849                    0.0, 0.0, 1.0, 0.0,
850                    0.0, 0.0, 0.0, 1.0,
851                    0.0, 0.0, 0.0, 0.0
852                ]
853            }
854            Filter::Opacity(api::PropertyBinding::Binding(..), _) |
855            Filter::SrgbToLinear |
856            Filter::LinearToSrgb |
857            Filter::ComponentTransfer |
858            Filter::Flood(..) => false,
859            Filter::SVGGraphNode(..) => false,
860        }
861    }
862
863
864    pub fn as_int(&self) -> i32 {
865        match *self {
867            Filter::Identity => 0, Filter::Contrast(..) => 0,
869            Filter::Grayscale(..) => 1,
870            Filter::HueRotate(..) => 2,
871            Filter::Invert(..) => 3,
872            Filter::Saturate(..) => 4,
873            Filter::Sepia(..) => 5,
874            Filter::Brightness(..) => 6,
875            Filter::ColorMatrix(..) => 7,
876            Filter::SrgbToLinear => 8,
877            Filter::LinearToSrgb => 9,
878            Filter::Flood(..) => 10,
879            Filter::ComponentTransfer => 11,
880            Filter::Blur { .. } => 12,
881            Filter::DropShadows(..) => 13,
882            Filter::Opacity(..) => 14,
883            Filter::SVGGraphNode(..) => unreachable!("SVGGraphNode handled elsewhere"),
884        }
885    }
886}
887
888impl From<FilterOp> for Filter {
889    fn from(op: FilterOp) -> Self {
890        match op {
891            FilterOp::Identity => Filter::Identity,
892            FilterOp::Blur(width, height) => Filter::Blur {
893                width,
894                height,
895                should_inflate: true,
896                edge_mode: BlurEdgeMode::Duplicate,
897            },
898            FilterOp::Brightness(b) => Filter::Brightness(b),
899            FilterOp::Contrast(c) => Filter::Contrast(c),
900            FilterOp::Grayscale(g) => Filter::Grayscale(g),
901            FilterOp::HueRotate(h) => Filter::HueRotate(h),
902            FilterOp::Invert(i) => Filter::Invert(i),
903            FilterOp::Opacity(binding, opacity) => Filter::Opacity(binding, opacity),
904            FilterOp::Saturate(s) => Filter::Saturate(s),
905            FilterOp::Sepia(s) => Filter::Sepia(s),
906            FilterOp::ColorMatrix(mat) => Filter::ColorMatrix(Box::new(mat)),
907            FilterOp::SrgbToLinear => Filter::SrgbToLinear,
908            FilterOp::LinearToSrgb => Filter::LinearToSrgb,
909            FilterOp::ComponentTransfer => Filter::ComponentTransfer,
910            FilterOp::DropShadow(shadow) => Filter::DropShadows(smallvec![shadow]),
911            FilterOp::Flood(color) => Filter::Flood(color),
912            FilterOp::SVGFEBlendColor{node} => Filter::SVGGraphNode(node.into(), FilterGraphOp::SVGFEBlendColor),
913            FilterOp::SVGFEBlendColorBurn{node} => Filter::SVGGraphNode(node.into(), FilterGraphOp::SVGFEBlendColorBurn),
914            FilterOp::SVGFEBlendColorDodge{node} => Filter::SVGGraphNode(node.into(), FilterGraphOp::SVGFEBlendColorDodge),
915            FilterOp::SVGFEBlendDarken{node} => Filter::SVGGraphNode(node.into(), FilterGraphOp::SVGFEBlendDarken),
916            FilterOp::SVGFEBlendDifference{node} => Filter::SVGGraphNode(node.into(), FilterGraphOp::SVGFEBlendDifference),
917            FilterOp::SVGFEBlendExclusion{node} => Filter::SVGGraphNode(node.into(), FilterGraphOp::SVGFEBlendExclusion),
918            FilterOp::SVGFEBlendHardLight{node} => Filter::SVGGraphNode(node.into(), FilterGraphOp::SVGFEBlendHardLight),
919            FilterOp::SVGFEBlendHue{node} => Filter::SVGGraphNode(node.into(), FilterGraphOp::SVGFEBlendHue),
920            FilterOp::SVGFEBlendLighten{node} => Filter::SVGGraphNode(node.into(), FilterGraphOp::SVGFEBlendLighten),
921            FilterOp::SVGFEBlendLuminosity{node} => Filter::SVGGraphNode(node.into(), FilterGraphOp::SVGFEBlendLuminosity),
922            FilterOp::SVGFEBlendMultiply{node} => Filter::SVGGraphNode(node.into(), FilterGraphOp::SVGFEBlendMultiply),
923            FilterOp::SVGFEBlendNormal{node} => Filter::SVGGraphNode(node.into(), FilterGraphOp::SVGFEBlendNormal),
924            FilterOp::SVGFEBlendOverlay{node} => Filter::SVGGraphNode(node.into(), FilterGraphOp::SVGFEBlendOverlay),
925            FilterOp::SVGFEBlendSaturation{node} => Filter::SVGGraphNode(node.into(), FilterGraphOp::SVGFEBlendSaturation),
926            FilterOp::SVGFEBlendScreen{node} => Filter::SVGGraphNode(node.into(), FilterGraphOp::SVGFEBlendScreen),
927            FilterOp::SVGFEBlendSoftLight{node} => Filter::SVGGraphNode(node.into(), FilterGraphOp::SVGFEBlendSoftLight),
928            FilterOp::SVGFEColorMatrix{node, values} => Filter::SVGGraphNode(node.into(), FilterGraphOp::SVGFEColorMatrix{values}),
929            FilterOp::SVGFEComponentTransfer{node} => Filter::SVGGraphNode(node.into(), FilterGraphOp::SVGFEComponentTransfer),
930            FilterOp::SVGFECompositeArithmetic{node, k1, k2, k3, k4} => Filter::SVGGraphNode(node.into(), FilterGraphOp::SVGFECompositeArithmetic{k1, k2, k3, k4}),
931            FilterOp::SVGFECompositeATop{node} => Filter::SVGGraphNode(node.into(), FilterGraphOp::SVGFECompositeATop),
932            FilterOp::SVGFECompositeIn{node} => Filter::SVGGraphNode(node.into(), FilterGraphOp::SVGFECompositeIn),
933            FilterOp::SVGFECompositeLighter{node} => Filter::SVGGraphNode(node.into(), FilterGraphOp::SVGFECompositeLighter),
934            FilterOp::SVGFECompositeOut{node} => Filter::SVGGraphNode(node.into(), FilterGraphOp::SVGFECompositeOut),
935            FilterOp::SVGFECompositeOver{node} => Filter::SVGGraphNode(node.into(), FilterGraphOp::SVGFECompositeOver),
936            FilterOp::SVGFECompositeXOR{node} => Filter::SVGGraphNode(node.into(), FilterGraphOp::SVGFECompositeXOR),
937            FilterOp::SVGFEConvolveMatrixEdgeModeDuplicate{node, order_x, order_y, kernel, divisor, bias, target_x, target_y, kernel_unit_length_x, kernel_unit_length_y, preserve_alpha} => Filter::SVGGraphNode(node.into(), FilterGraphOp::SVGFEConvolveMatrixEdgeModeDuplicate{order_x, order_y, kernel, divisor, bias, target_x, target_y, kernel_unit_length_x, kernel_unit_length_y, preserve_alpha}),
938            FilterOp::SVGFEConvolveMatrixEdgeModeNone{node, order_x, order_y, kernel, divisor, bias, target_x, target_y, kernel_unit_length_x, kernel_unit_length_y, preserve_alpha} => Filter::SVGGraphNode(node.into(), FilterGraphOp::SVGFEConvolveMatrixEdgeModeNone{order_x, order_y, kernel, divisor, bias, target_x, target_y, kernel_unit_length_x, kernel_unit_length_y, preserve_alpha}),
939            FilterOp::SVGFEConvolveMatrixEdgeModeWrap{node, order_x, order_y, kernel, divisor, bias, target_x, target_y, kernel_unit_length_x, kernel_unit_length_y, preserve_alpha} => Filter::SVGGraphNode(node.into(), FilterGraphOp::SVGFEConvolveMatrixEdgeModeWrap{order_x, order_y, kernel, divisor, bias, target_x, target_y, kernel_unit_length_x, kernel_unit_length_y, preserve_alpha}),
940            FilterOp::SVGFEDiffuseLightingDistant{node, surface_scale, diffuse_constant, kernel_unit_length_x, kernel_unit_length_y, azimuth, elevation} => Filter::SVGGraphNode(node.into(), FilterGraphOp::SVGFEDiffuseLightingDistant{surface_scale, diffuse_constant, kernel_unit_length_x, kernel_unit_length_y, azimuth, elevation}),
941            FilterOp::SVGFEDiffuseLightingPoint{node, surface_scale, diffuse_constant, kernel_unit_length_x, kernel_unit_length_y, x, y, z} => Filter::SVGGraphNode(node.into(), FilterGraphOp::SVGFEDiffuseLightingPoint{surface_scale, diffuse_constant, kernel_unit_length_x, kernel_unit_length_y, x, y, z}),
942            FilterOp::SVGFEDiffuseLightingSpot{node, surface_scale, diffuse_constant, kernel_unit_length_x, kernel_unit_length_y, x, y, z, points_at_x, points_at_y, points_at_z, cone_exponent, limiting_cone_angle} => Filter::SVGGraphNode(node.into(), FilterGraphOp::SVGFEDiffuseLightingSpot{surface_scale, diffuse_constant, kernel_unit_length_x, kernel_unit_length_y, x, y, z, points_at_x, points_at_y, points_at_z, cone_exponent, limiting_cone_angle}),
943            FilterOp::SVGFEDisplacementMap{node, scale, x_channel_selector, y_channel_selector} => Filter::SVGGraphNode(node.into(), FilterGraphOp::SVGFEDisplacementMap{scale, x_channel_selector, y_channel_selector}),
944            FilterOp::SVGFEDropShadow{node, color, dx, dy, std_deviation_x, std_deviation_y} => Filter::SVGGraphNode(node.into(), FilterGraphOp::SVGFEDropShadow{color, dx, dy, std_deviation_x, std_deviation_y}),
945            FilterOp::SVGFEFlood{node, color} => Filter::SVGGraphNode(node.into(), FilterGraphOp::SVGFEFlood{color}),
946            FilterOp::SVGFEGaussianBlur{node, std_deviation_x, std_deviation_y} => Filter::SVGGraphNode(node.into(), FilterGraphOp::SVGFEGaussianBlur{std_deviation_x, std_deviation_y}),
947            FilterOp::SVGFEIdentity{node} => Filter::SVGGraphNode(node.into(), FilterGraphOp::SVGFEIdentity),
948            FilterOp::SVGFEImage{node, sampling_filter, matrix} => Filter::SVGGraphNode(node.into(), FilterGraphOp::SVGFEImage{sampling_filter, matrix}),
949            FilterOp::SVGFEMorphologyDilate{node, radius_x, radius_y} => Filter::SVGGraphNode(node.into(), FilterGraphOp::SVGFEMorphologyDilate{radius_x, radius_y}),
950            FilterOp::SVGFEMorphologyErode{node, radius_x, radius_y} => Filter::SVGGraphNode(node.into(), FilterGraphOp::SVGFEMorphologyErode{radius_x, radius_y}),
951            FilterOp::SVGFEOffset{node, offset_x, offset_y} => {
952                Filter::SVGGraphNode(
953                    FilterGraphNode {
954                        kept_by_optimizer: true, linear: node.linear,
956                        inflate: 0, inputs: [FilterGraphPictureReference {
958                            buffer_id: node.input.buffer_id,
959                            offset: LayoutVector2D::new(offset_x, offset_y),
960                            subregion: LayoutRect::zero(),
961                            inflate: 0,
962                            source_padding: LayoutRect::zero(),
963                            target_padding: LayoutRect::zero(),
964                        }].to_vec(),
965                        subregion: node.subregion,
966                    },
967                    FilterGraphOp::SVGFEIdentity,
968                )
969            },
970            FilterOp::SVGFEOpacity{node, valuebinding, value} => Filter::SVGGraphNode(node.into(), FilterGraphOp::SVGFEOpacity{valuebinding, value}),
971            FilterOp::SVGFESourceAlpha{node} => Filter::SVGGraphNode(node.into(), FilterGraphOp::SVGFESourceAlpha),
972            FilterOp::SVGFESourceGraphic{node} => Filter::SVGGraphNode(node.into(), FilterGraphOp::SVGFESourceGraphic),
973            FilterOp::SVGFESpecularLightingDistant{node, surface_scale, specular_constant, specular_exponent, kernel_unit_length_x, kernel_unit_length_y, azimuth, elevation} => Filter::SVGGraphNode(node.into(), FilterGraphOp::SVGFESpecularLightingDistant{surface_scale, specular_constant, specular_exponent, kernel_unit_length_x, kernel_unit_length_y, azimuth, elevation}),
974            FilterOp::SVGFESpecularLightingPoint{node, surface_scale, specular_constant, specular_exponent, kernel_unit_length_x, kernel_unit_length_y, x, y, z} => Filter::SVGGraphNode(node.into(), FilterGraphOp::SVGFESpecularLightingPoint{surface_scale, specular_constant, specular_exponent, kernel_unit_length_x, kernel_unit_length_y, x, y, z}),
975            FilterOp::SVGFESpecularLightingSpot{node, surface_scale, specular_constant, specular_exponent, kernel_unit_length_x, kernel_unit_length_y, x, y, z, points_at_x, points_at_y, points_at_z, cone_exponent, limiting_cone_angle} => Filter::SVGGraphNode(node.into(), FilterGraphOp::SVGFESpecularLightingSpot{surface_scale, specular_constant, specular_exponent, kernel_unit_length_x, kernel_unit_length_y, x, y, z, points_at_x, points_at_y, points_at_z, cone_exponent, limiting_cone_angle}),
976            FilterOp::SVGFETile{node} => Filter::SVGGraphNode(node.into(), FilterGraphOp::SVGFETile),
977            FilterOp::SVGFEToAlpha{node} => Filter::SVGGraphNode(node.into(), FilterGraphOp::SVGFEToAlpha),
978            FilterOp::SVGFETurbulenceWithFractalNoiseWithNoStitching{node, base_frequency_x, base_frequency_y, num_octaves, seed} => Filter::SVGGraphNode(node.into(), FilterGraphOp::SVGFETurbulenceWithFractalNoiseWithNoStitching{base_frequency_x, base_frequency_y, num_octaves, seed}),
979            FilterOp::SVGFETurbulenceWithFractalNoiseWithStitching{node, base_frequency_x, base_frequency_y, num_octaves, seed} => Filter::SVGGraphNode(node.into(), FilterGraphOp::SVGFETurbulenceWithFractalNoiseWithStitching{base_frequency_x, base_frequency_y, num_octaves, seed}),
980            FilterOp::SVGFETurbulenceWithTurbulenceNoiseWithNoStitching{node, base_frequency_x, base_frequency_y, num_octaves, seed} => Filter::SVGGraphNode(node.into(), FilterGraphOp::SVGFETurbulenceWithTurbulenceNoiseWithNoStitching{base_frequency_x, base_frequency_y, num_octaves, seed}),
981            FilterOp::SVGFETurbulenceWithTurbulenceNoiseWithStitching{node, base_frequency_x, base_frequency_y, num_octaves, seed} => Filter::SVGGraphNode(node.into(), FilterGraphOp::SVGFETurbulenceWithTurbulenceNoiseWithStitching{base_frequency_x, base_frequency_y, num_octaves, seed}),
982        }
983    }
984}
985
986#[cfg_attr(feature = "capture", derive(Serialize))]
987#[cfg_attr(feature = "replay", derive(Deserialize))]
988#[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, PartialEq)]
989pub enum Swizzle {
990    Rgba,
991    Bgra,
992}
993
994impl Default for Swizzle {
995    fn default() -> Self {
996        Swizzle::Rgba
997    }
998}
999
1000#[cfg_attr(feature = "capture", derive(Serialize))]
1002#[cfg_attr(feature = "replay", derive(Deserialize))]
1003#[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, PartialEq)]
1004pub struct SwizzleSettings {
1005    pub bgra8_sampling_swizzle: Swizzle,
1007}
1008
1009#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
1018#[cfg_attr(feature = "capture", derive(Serialize))]
1019#[cfg_attr(feature = "replay", derive(Deserialize))]
1020pub struct CacheTextureId(pub u32);
1021
1022impl CacheTextureId {
1023    pub const INVALID: CacheTextureId = CacheTextureId(!0);
1024}
1025
1026#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
1027#[cfg_attr(feature = "capture", derive(Serialize))]
1028#[cfg_attr(feature = "replay", derive(Deserialize))]
1029pub struct DeferredResolveIndex(pub u32);
1030
1031#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
1032#[cfg_attr(feature = "capture", derive(Serialize))]
1033#[cfg_attr(feature = "replay", derive(Deserialize))]
1034pub struct TextureSourceExternal {
1035    pub index: DeferredResolveIndex,
1036    pub kind: ImageBufferKind,
1037    pub normalized_uvs: bool,
1038}
1039
1040#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
1042#[cfg_attr(feature = "capture", derive(Serialize))]
1043#[cfg_attr(feature = "replay", derive(Deserialize))]
1044pub enum TextureSource {
1045    Invalid,
1047    TextureCache(CacheTextureId, Swizzle),
1049    External(TextureSourceExternal),
1051    Dummy,
1054}
1055
1056impl TextureSource {
1057    pub fn image_buffer_kind(&self) -> ImageBufferKind {
1058        match *self {
1059            TextureSource::TextureCache(..) => ImageBufferKind::Texture2D,
1060
1061            TextureSource::External(TextureSourceExternal { kind, .. }) => kind,
1062
1063            TextureSource::Dummy => ImageBufferKind::Texture2D,
1065
1066            TextureSource::Invalid => ImageBufferKind::Texture2D,
1067        }
1068    }
1069
1070    pub fn uses_normalized_uvs(&self) -> bool {
1071        match *self {
1072            TextureSource::External(TextureSourceExternal { normalized_uvs, .. }) => normalized_uvs,
1073            _ => false,
1074        }
1075    }
1076
1077    #[inline]
1078    pub fn is_compatible(
1079        &self,
1080        other: &TextureSource,
1081    ) -> bool {
1082        *self == TextureSource::Invalid ||
1083        *other == TextureSource::Invalid ||
1084        self == other
1085    }
1086}
1087
1088#[derive(Copy, Clone, Debug, PartialEq)]
1089#[cfg_attr(feature = "capture", derive(Serialize))]
1090#[cfg_attr(feature = "replay", derive(Deserialize))]
1091pub struct RenderTargetInfo {
1092    pub has_depth: bool,
1093}
1094
1095#[derive(Debug)]
1096pub enum TextureUpdateSource {
1097    External {
1098        id: ExternalImageId,
1099        channel_index: u8,
1100    },
1101    Bytes { data: Arc<Vec<u8>> },
1102    DebugClear,
1105}
1106
1107#[derive(Debug)]
1109pub struct TextureCacheAllocation {
1110    pub id: CacheTextureId,
1112    pub kind: TextureCacheAllocationKind,
1114}
1115
1116#[derive(Copy, Clone, Debug, Eq, PartialEq)]
1118#[cfg_attr(feature = "capture", derive(Serialize))]
1119#[cfg_attr(feature = "replay", derive(Deserialize))]
1120pub enum TextureCacheCategory {
1121    Atlas,
1122    Standalone,
1123    PictureTile,
1124    RenderTarget,
1125}
1126
1127#[derive(Copy, Clone, Debug, Eq, PartialEq)]
1129pub struct TextureCacheAllocInfo {
1130    pub width: i32,
1131    pub height: i32,
1132    pub format: ImageFormat,
1133    pub filter: TextureFilter,
1134    pub target: ImageBufferKind,
1135    pub is_shared_cache: bool,
1137    pub has_depth: bool,
1139    pub category: TextureCacheCategory
1140}
1141
1142#[derive(Debug)]
1144pub enum TextureCacheAllocationKind {
1145    Alloc(TextureCacheAllocInfo),
1147    Reset(TextureCacheAllocInfo),
1149    Free,
1151}
1152
1153#[derive(Debug)]
1155pub struct TextureCacheUpdate {
1156    pub rect: DeviceIntRect,
1157    pub stride: Option<i32>,
1158    pub offset: i32,
1159    pub format_override: Option<ImageFormat>,
1160    pub source: TextureUpdateSource,
1161}
1162
1163#[derive(Debug)]
1165pub struct TextureCacheCopy {
1166    pub src_rect: DeviceIntRect,
1167    pub dst_rect: DeviceIntRect,
1168}
1169
1170#[derive(Default)]
1176pub struct TextureUpdateList {
1177    pub clears_shared_cache: bool,
1180    pub allocations: Vec<TextureCacheAllocation>,
1182    pub updates: FastHashMap<CacheTextureId, Vec<TextureCacheUpdate>>,
1184    pub copies: FastHashMap<(CacheTextureId, CacheTextureId), Vec<TextureCacheCopy>>,
1187}
1188
1189impl TextureUpdateList {
1190    pub fn new() -> Self {
1192        TextureUpdateList {
1193            clears_shared_cache: false,
1194            allocations: Vec::new(),
1195            updates: FastHashMap::default(),
1196            copies: FastHashMap::default(),
1197        }
1198    }
1199
1200    pub fn is_nop(&self) -> bool {
1202        self.allocations.is_empty() && self.updates.is_empty()
1203    }
1204
1205    #[inline]
1207    pub fn note_clear(&mut self) {
1208        self.clears_shared_cache = true;
1209    }
1210
1211    #[inline]
1213    pub fn push_update(&mut self, id: CacheTextureId, update: TextureCacheUpdate) {
1214        self.updates
1215            .entry(id)
1216            .or_default()
1217            .push(update);
1218    }
1219
1220    #[cold]
1223    pub fn push_debug_clear(
1224        &mut self,
1225        id: CacheTextureId,
1226        origin: DeviceIntPoint,
1227        width: i32,
1228        height: i32,
1229    ) {
1230        let size = DeviceIntSize::new(width, height);
1231        let rect = DeviceIntRect::from_origin_and_size(origin, size);
1232        self.push_update(id, TextureCacheUpdate {
1233            rect,
1234            stride: None,
1235            offset: 0,
1236            format_override: None,
1237            source: TextureUpdateSource::DebugClear,
1238        });
1239    }
1240
1241
1242    pub fn push_alloc(&mut self, id: CacheTextureId, info: TextureCacheAllocInfo) {
1244        debug_assert!(!self.allocations.iter().any(|x| x.id == id));
1245        self.allocations.push(TextureCacheAllocation {
1246            id,
1247            kind: TextureCacheAllocationKind::Alloc(info),
1248        });
1249    }
1250
1251    pub fn push_reset(&mut self, id: CacheTextureId, info: TextureCacheAllocInfo) {
1254        self.debug_assert_coalesced(id);
1255
1256        self.updates.remove(&id);
1258
1259        if let Some(cur) = self.allocations.iter_mut().find(|x| x.id == id) {
1261            match cur.kind {
1262                TextureCacheAllocationKind::Alloc(ref mut i) => *i = info,
1263                TextureCacheAllocationKind::Reset(ref mut i) => *i = info,
1264                TextureCacheAllocationKind::Free => panic!("Resetting freed texture"),
1265            }
1266            return
1267        }
1268
1269        self.allocations.push(TextureCacheAllocation {
1270            id,
1271            kind: TextureCacheAllocationKind::Reset(info),
1272        });
1273    }
1274
1275    pub fn push_free(&mut self, id: CacheTextureId) {
1278        self.debug_assert_coalesced(id);
1279
1280        self.updates.remove(&id);
1282
1283        let idx = self.allocations.iter().position(|x| x.id == id);
1286        let removed_kind = idx.map(|i| self.allocations.remove(i).kind);
1287        match removed_kind {
1288            Some(TextureCacheAllocationKind::Alloc(..)) => { },
1289            Some(TextureCacheAllocationKind::Free) => panic!("Double free"),
1290            Some(TextureCacheAllocationKind::Reset(..)) |
1291            None => {
1292                self.allocations.push(TextureCacheAllocation {
1293                    id,
1294                    kind: TextureCacheAllocationKind::Free,
1295                });
1296            }
1297        };
1298    }
1299
1300    pub fn push_copy(
1306        &mut self,
1307        src_id: CacheTextureId, src_rect: &DeviceIntRect,
1308        dst_id: CacheTextureId, dst_rect: &DeviceIntRect,
1309    ) {
1310        debug_assert_eq!(src_rect.size(), dst_rect.size());
1311        self.copies.entry((src_id, dst_id))
1312            .or_insert_with(Vec::new)
1313            .push(TextureCacheCopy {
1314                src_rect: *src_rect,
1315                dst_rect: *dst_rect,
1316            });
1317    }
1318
1319    fn debug_assert_coalesced(&self, id: CacheTextureId) {
1320        debug_assert!(
1321            self.allocations.iter().filter(|x| x.id == id).count() <= 1,
1322            "Allocations should have been coalesced",
1323        );
1324    }
1325}
1326
1327pub struct ResourceUpdateList {
1330    pub native_surface_updates: Vec<NativeSurfaceOperation>,
1332
1333    pub texture_updates: TextureUpdateList,
1335}
1336
1337impl ResourceUpdateList {
1338    pub fn is_nop(&self) -> bool {
1340        self.texture_updates.is_nop() && self.native_surface_updates.is_empty()
1341    }
1342}
1343
1344pub struct RenderedDocument {
1346    pub frame: Frame,
1347    pub profile: TransactionProfile,
1348    pub render_reasons: RenderReasons,
1349    pub frame_stats: Option<FullFrameStats>
1350}
1351
1352pub enum DebugOutput {
1353    #[cfg(feature = "capture")]
1354    SaveCapture(CaptureConfig, Vec<ExternalCaptureImage>),
1355    #[cfg(feature = "replay")]
1356    LoadCapture(CaptureConfig, Vec<PlainExternalImage>),
1357}
1358
1359#[allow(dead_code)]
1360pub enum ResultMsg {
1361    DebugCommand(DebugCommand),
1362    DebugOutput(DebugOutput),
1363    RefreshShader(PathBuf),
1364    UpdateGpuCache(GpuCacheUpdateList),
1365    UpdateResources {
1366        resource_updates: ResourceUpdateList,
1367        memory_pressure: bool,
1368    },
1369    PublishPipelineInfo(PipelineInfo),
1370    PublishDocument(
1371        FramePublishId,
1372        DocumentId,
1373        RenderedDocument,
1374        ResourceUpdateList,
1375    ),
1376    RenderDocumentOffscreen(
1377        DocumentId,
1378        RenderedDocument,
1379        ResourceUpdateList,
1380    ),
1381    AppendNotificationRequests(Vec<NotificationRequest>),
1382    SetParameter(Parameter),
1383    ForceRedraw,
1384}
1385
1386#[derive(Copy, Clone, Debug)]
1388pub struct LayoutPrimitiveInfo {
1389    pub rect: LayoutRect,
1392    pub clip_rect: LayoutRect,
1393    pub flags: PrimitiveFlags,
1394}
1395
1396impl LayoutPrimitiveInfo {
1397    pub fn with_clip_rect(rect: LayoutRect, clip_rect: LayoutRect) -> Self {
1398        Self {
1399            rect,
1400            clip_rect,
1401            flags: PrimitiveFlags::default(),
1402        }
1403    }
1404}
1405
1406#[cfg_attr(feature = "capture", derive(Serialize))]
1409#[cfg_attr(feature = "replay", derive(Deserialize))]
1410#[derive(Copy, Clone, PartialEq, Debug, Eq, Hash)]
1411pub struct PipelineInstanceId(u32);
1412
1413impl PipelineInstanceId {
1414    pub fn new(id: u32) -> Self {
1415        PipelineInstanceId(id)
1416    }
1417}