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}