webrender/prim_store/picture.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
5use api::{
6 ColorU, MixBlendMode, FilterPrimitiveInput, FilterPrimitiveKind,
7 ColorSpace, PropertyBinding, PropertyBindingId, CompositeOperator,
8 RasterSpace, FilterOpGraphPictureBufferId,
9};
10use api::units::Au;
11use crate::scene_building::IsVisible;
12use crate::filterdata::SFilterData;
13use crate::gpu_types::BlurEdgeMode;
14use crate::intern::ItemUid;
15use crate::intern::{Internable, InternDebug, Handle as InternHandle};
16use crate::internal_types::{LayoutPrimitiveInfo, FilterGraphPictureReference,
17 FilterGraphOp, FilterGraphNode, SVGFE_CONVOLVE_VALUES_LIMIT, Filter};
18use crate::picture::PictureCompositeMode;
19use crate::prim_store::{
20 PrimitiveInstanceKind, PrimitiveStore, VectorKey,
21 InternablePrimitive,
22};
23
24#[cfg_attr(feature = "capture", derive(Serialize))]
25#[cfg_attr(feature = "replay", derive(Deserialize))]
26#[derive(Debug, Clone, MallocSizeOf, PartialEq, Hash, Eq)]
27pub enum CompositeOperatorKey {
28 Over,
29 In,
30 Out,
31 Atop,
32 Xor,
33 Lighter,
34 Arithmetic([Au; 4]),
35}
36
37impl From<CompositeOperator> for CompositeOperatorKey {
38 fn from(operator: CompositeOperator) -> Self {
39 match operator {
40 CompositeOperator::Over => CompositeOperatorKey::Over,
41 CompositeOperator::In => CompositeOperatorKey::In,
42 CompositeOperator::Out => CompositeOperatorKey::Out,
43 CompositeOperator::Atop => CompositeOperatorKey::Atop,
44 CompositeOperator::Xor => CompositeOperatorKey::Xor,
45 CompositeOperator::Lighter => CompositeOperatorKey::Lighter,
46 CompositeOperator::Arithmetic(k_vals) => {
47 let k_vals = [
48 Au::from_f32_px(k_vals[0]),
49 Au::from_f32_px(k_vals[1]),
50 Au::from_f32_px(k_vals[2]),
51 Au::from_f32_px(k_vals[3]),
52 ];
53 CompositeOperatorKey::Arithmetic(k_vals)
54 }
55 }
56 }
57}
58
59#[cfg_attr(feature = "capture", derive(Serialize))]
60#[cfg_attr(feature = "replay", derive(Deserialize))]
61#[derive(Debug, Clone, MallocSizeOf, PartialEq, Hash, Eq)]
62pub enum FilterPrimitiveKey {
63 Identity(ColorSpace, FilterPrimitiveInput),
64 Flood(ColorSpace, ColorU),
65 Blend(ColorSpace, MixBlendMode, FilterPrimitiveInput, FilterPrimitiveInput),
66 Blur(ColorSpace, Au, Au, FilterPrimitiveInput),
67 Opacity(ColorSpace, Au, FilterPrimitiveInput),
68 ColorMatrix(ColorSpace, [Au; 20], FilterPrimitiveInput),
69 DropShadow(ColorSpace, (VectorKey, Au, ColorU), FilterPrimitiveInput),
70 ComponentTransfer(ColorSpace, FilterPrimitiveInput, Vec<SFilterData>),
71 Offset(ColorSpace, FilterPrimitiveInput, VectorKey),
72 Composite(ColorSpace, FilterPrimitiveInput, FilterPrimitiveInput, CompositeOperatorKey),
73}
74
75#[cfg_attr(feature = "capture", derive(Serialize))]
76#[cfg_attr(feature = "replay", derive(Deserialize))]
77#[derive(Debug, Clone, Copy, Default, MallocSizeOf, PartialEq, Hash, Eq)]
78pub enum FilterGraphPictureBufferIdKey {
79 #[default]
80 /// empty slot in feMerge inputs
81 None,
82 /// reference to another (earlier) node in filter graph
83 BufferId(i16),
84}
85
86#[cfg_attr(feature = "capture", derive(Serialize))]
87#[cfg_attr(feature = "replay", derive(Deserialize))]
88#[derive(Debug, Clone, Copy, Default, MallocSizeOf, PartialEq, Hash, Eq)]
89pub struct FilterGraphPictureReferenceKey {
90 /// Id of the picture in question in a namespace unique to this filter DAG,
91 /// some are special values like
92 /// FilterPrimitiveDescription::kPrimitiveIndexSourceGraphic.
93 pub buffer_id: FilterGraphPictureBufferIdKey,
94 /// Place the input image here in Layout space (like node.subregion)
95 pub subregion: [Au; 4],
96 /// Translate the subregion by this amount
97 pub offset: [Au; 2],
98}
99
100impl From<FilterGraphPictureReference> for FilterGraphPictureReferenceKey {
101 fn from(pic: FilterGraphPictureReference) -> Self {
102 FilterGraphPictureReferenceKey{
103 buffer_id: match pic.buffer_id {
104 FilterOpGraphPictureBufferId::None => FilterGraphPictureBufferIdKey::None,
105 FilterOpGraphPictureBufferId::BufferId(id) => FilterGraphPictureBufferIdKey::BufferId(id),
106 },
107 subregion: [
108 Au::from_f32_px(pic.subregion.min.x),
109 Au::from_f32_px(pic.subregion.min.y),
110 Au::from_f32_px(pic.subregion.max.x),
111 Au::from_f32_px(pic.subregion.max.y),
112 ],
113 offset: [
114 Au::from_f32_px(pic.offset.x),
115 Au::from_f32_px(pic.offset.y),
116 ],
117 }
118 }
119}
120
121#[cfg_attr(feature = "capture", derive(Serialize))]
122#[cfg_attr(feature = "replay", derive(Deserialize))]
123#[derive(Debug, Clone, MallocSizeOf, PartialEq, Hash, Eq)]
124pub enum FilterGraphOpKey {
125 /// combine 2 images with SVG_FEBLEND_MODE_DARKEN
126 /// parameters: FilterOpGraphNode
127 /// SVG filter semantics - selectable input(s), selectable between linear
128 /// (default) and sRGB color space for calculations
129 /// Spec: https://www.w3.org/TR/filter-effects-1/#feBlendElement
130 SVGFEBlendDarken,
131 /// combine 2 images with SVG_FEBLEND_MODE_LIGHTEN
132 /// parameters: FilterOpGraphNode
133 /// SVG filter semantics - selectable input(s), selectable between linear
134 /// (default) and sRGB color space for calculations
135 /// Spec: https://www.w3.org/TR/filter-effects-1/#feBlendElement
136 SVGFEBlendLighten,
137 /// combine 2 images with SVG_FEBLEND_MODE_MULTIPLY
138 /// parameters: FilterOpGraphNode
139 /// SVG filter semantics - selectable input(s), selectable between linear
140 /// (default) and sRGB color space for calculations
141 /// Spec: https://www.w3.org/TR/filter-effects-1/#feBlendElement
142 SVGFEBlendMultiply,
143 /// combine 2 images with SVG_FEBLEND_MODE_NORMAL
144 /// parameters: FilterOpGraphNode
145 /// SVG filter semantics - selectable input(s), selectable between linear
146 /// (default) and sRGB color space for calculations
147 /// Spec: https://www.w3.org/TR/filter-effects-1/#feBlendElement
148 SVGFEBlendNormal,
149 /// combine 2 images with SVG_FEBLEND_MODE_SCREEN
150 /// parameters: FilterOpGraphNode
151 /// SVG filter semantics - selectable input(s), selectable between linear
152 /// (default) and sRGB color space for calculations
153 /// Spec: https://www.w3.org/TR/filter-effects-1/#feBlendElement
154 SVGFEBlendScreen,
155 /// combine 2 images with SVG_FEBLEND_MODE_OVERLAY
156 /// parameters: FilterOpGraphNode
157 /// SVG filter semantics - selectable input(s), selectable between linear
158 /// (default) and sRGB color space for calculations
159 /// Source: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode
160 SVGFEBlendOverlay,
161 /// combine 2 images with SVG_FEBLEND_MODE_COLOR_DODGE
162 /// parameters: FilterOpGraphNode
163 /// SVG filter semantics - selectable input(s), selectable between linear
164 /// (default) and sRGB color space for calculations
165 /// Source: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode
166 SVGFEBlendColorDodge,
167 /// combine 2 images with SVG_FEBLEND_MODE_COLOR_BURN
168 /// parameters: FilterOpGraphNode
169 /// SVG filter semantics - selectable input(s), selectable between linear
170 /// (default) and sRGB color space for calculations
171 /// Source: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode
172 SVGFEBlendColorBurn,
173 /// combine 2 images with SVG_FEBLEND_MODE_HARD_LIGHT
174 /// parameters: FilterOpGraphNode
175 /// SVG filter semantics - selectable input(s), selectable between linear
176 /// (default) and sRGB color space for calculations
177 /// Source: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode
178 SVGFEBlendHardLight,
179 /// combine 2 images with SVG_FEBLEND_MODE_SOFT_LIGHT
180 /// parameters: FilterOpGraphNode
181 /// SVG filter semantics - selectable input(s), selectable between linear
182 /// (default) and sRGB color space for calculations
183 /// Source: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode
184 SVGFEBlendSoftLight,
185 /// combine 2 images with SVG_FEBLEND_MODE_DIFFERENCE
186 /// parameters: FilterOpGraphNode
187 /// SVG filter semantics - selectable input(s), selectable between linear
188 /// (default) and sRGB color space for calculations
189 /// Source: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode
190 SVGFEBlendDifference,
191 /// combine 2 images with SVG_FEBLEND_MODE_EXCLUSION
192 /// parameters: FilterOpGraphNode
193 /// SVG filter semantics - selectable input(s), selectable between linear
194 /// (default) and sRGB color space for calculations
195 /// Source: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode
196 SVGFEBlendExclusion,
197 /// combine 2 images with SVG_FEBLEND_MODE_HUE
198 /// parameters: FilterOpGraphNode
199 /// SVG filter semantics - selectable input(s), selectable between linear
200 /// (default) and sRGB color space for calculations
201 /// Source: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode
202 SVGFEBlendHue,
203 /// combine 2 images with SVG_FEBLEND_MODE_SATURATION
204 /// parameters: FilterOpGraphNode
205 /// SVG filter semantics - selectable input(s), selectable between linear
206 /// (default) and sRGB color space for calculations
207 /// Source: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode
208 SVGFEBlendSaturation,
209 /// combine 2 images with SVG_FEBLEND_MODE_COLOR
210 /// parameters: FilterOpGraphNode
211 /// SVG filter semantics - selectable input(s), selectable between linear
212 /// (default) and sRGB color space for calculations
213 /// Source: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode
214 SVGFEBlendColor,
215 /// combine 2 images with SVG_FEBLEND_MODE_LUMINOSITY
216 /// parameters: FilterOpGraphNode
217 /// SVG filter semantics - selectable input(s), selectable between linear
218 /// (default) and sRGB color space for calculations
219 /// Source: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode
220 SVGFEBlendLuminosity,
221 /// transform colors of image through 5x4 color matrix (transposed for
222 /// efficiency)
223 /// parameters: FilterOpGraphNode, matrix[5][4]
224 /// SVG filter semantics - selectable input(s), selectable between linear
225 /// (default) and sRGB color space for calculations
226 /// Spec: https://www.w3.org/TR/filter-effects-1/#feColorMatrixElement
227 SVGFEColorMatrix{values: [Au; 20]},
228 /// transform colors of image through configurable gradients with component
229 /// swizzle
230 /// parameters: FilterOpGraphNode, FilterData
231 /// SVG filter semantics - selectable input(s), selectable between linear
232 /// (default) and sRGB color space for calculations
233 /// Spec: https://www.w3.org/TR/filter-effects-1/#feComponentTransferElement
234 SVGFEComponentTransferInterned{handle: ItemUid, creates_pixels: bool},
235 /// composite 2 images with chosen composite mode with parameters for that
236 /// mode
237 /// parameters: FilterOpGraphNode, k1, k2, k3, k4
238 /// SVG filter semantics - selectable input(s), selectable between linear
239 /// (default) and sRGB color space for calculations
240 /// Spec: https://www.w3.org/TR/filter-effects-1/#feCompositeElement
241 SVGFECompositeArithmetic{k1: Au, k2: Au, k3: Au, k4: Au},
242 /// composite 2 images with chosen composite mode with parameters for that
243 /// mode
244 /// parameters: FilterOpGraphNode
245 /// SVG filter semantics - selectable input(s), selectable between linear
246 /// (default) and sRGB color space for calculations
247 /// Spec: https://www.w3.org/TR/filter-effects-1/#feCompositeElement
248 SVGFECompositeATop,
249 /// composite 2 images with chosen composite mode with parameters for that
250 /// mode
251 /// parameters: FilterOpGraphNode
252 /// SVG filter semantics - selectable input(s), selectable between linear
253 /// (default) and sRGB color space for calculations
254 /// Spec: https://www.w3.org/TR/filter-effects-1/#feCompositeElement
255 SVGFECompositeIn,
256 /// composite 2 images with chosen composite mode with parameters for that
257 /// mode
258 /// parameters: FilterOpGraphNode
259 /// SVG filter semantics - selectable input(s), selectable between linear
260 /// (default) and sRGB color space for calculations
261 /// Docs: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/feComposite
262 SVGFECompositeLighter,
263 /// composite 2 images with chosen composite mode with parameters for that
264 /// mode
265 /// parameters: FilterOpGraphNode
266 /// SVG filter semantics - selectable input(s), selectable between linear
267 /// (default) and sRGB color space for calculations
268 /// Spec: https://www.w3.org/TR/filter-effects-1/#feCompositeElement
269 SVGFECompositeOut,
270 /// composite 2 images with chosen composite mode with parameters for that
271 /// mode
272 /// parameters: FilterOpGraphNode
273 /// SVG filter semantics - selectable input(s), selectable between linear
274 /// (default) and sRGB color space for calculations
275 /// Spec: https://www.w3.org/TR/filter-effects-1/#feCompositeElement
276 SVGFECompositeOver,
277 /// composite 2 images with chosen composite mode with parameters for that
278 /// mode
279 /// parameters: FilterOpGraphNode
280 /// SVG filter semantics - selectable input(s), selectable between linear
281 /// (default) and sRGB color space for calculations
282 /// Spec: https://www.w3.org/TR/filter-effects-1/#feCompositeElement
283 SVGFECompositeXOR,
284 /// transform image through convolution matrix of up to 25 values (spec
285 /// allows more but for performance reasons we do not)
286 /// parameters: FilterOpGraphNode, orderX, orderY, kernelValues[25],
287 /// divisor, bias, targetX, targetY, kernelUnitLengthX, kernelUnitLengthY,
288 /// preserveAlpha
289 /// SVG filter semantics - selectable input(s), selectable between linear
290 /// (default) and sRGB color space for calculations
291 /// Spec: https://www.w3.org/TR/filter-effects-1/#feConvolveMatrixElement
292 SVGFEConvolveMatrixEdgeModeDuplicate{order_x: i32, order_y: i32,
293 kernel: [Au; SVGFE_CONVOLVE_VALUES_LIMIT], divisor: Au, bias: Au,
294 target_x: i32, target_y: i32, kernel_unit_length_x: Au,
295 kernel_unit_length_y: Au, preserve_alpha: i32},
296 /// transform image through convolution matrix of up to 25 values (spec
297 /// allows more but for performance reasons we do not)
298 /// parameters: FilterOpGraphNode, orderX, orderY, kernelValues[25],
299 /// divisor, bias, targetX, targetY, kernelUnitLengthX, kernelUnitLengthY,
300 /// preserveAlpha
301 /// SVG filter semantics - selectable input(s), selectable between linear
302 /// (default) and sRGB color space for calculations
303 /// Spec: https://www.w3.org/TR/filter-effects-1/#feConvolveMatrixElement
304 SVGFEConvolveMatrixEdgeModeNone{order_x: i32, order_y: i32,
305 kernel: [Au; SVGFE_CONVOLVE_VALUES_LIMIT], divisor: Au, bias: Au,
306 target_x: i32, target_y: i32, kernel_unit_length_x: Au,
307 kernel_unit_length_y: Au, preserve_alpha: i32},
308 /// transform image through convolution matrix of up to 25 values (spec
309 /// allows more but for performance reasons we do not)
310 /// parameters: FilterOpGraphNode, orderX, orderY, kernelValues[25],
311 /// divisor, bias, targetX, targetY, kernelUnitLengthX, kernelUnitLengthY,
312 /// preserveAlpha
313 /// SVG filter semantics - selectable input(s), selectable between linear
314 /// (default) and sRGB color space for calculations
315 /// Spec: https://www.w3.org/TR/filter-effects-1/#feConvolveMatrixElement
316 SVGFEConvolveMatrixEdgeModeWrap{order_x: i32, order_y: i32,
317 kernel: [Au; SVGFE_CONVOLVE_VALUES_LIMIT], divisor: Au, bias: Au,
318 target_x: i32, target_y: i32, kernel_unit_length_x: Au,
319 kernel_unit_length_y: Au, preserve_alpha: i32},
320 /// calculate lighting based on heightmap image with provided values for a
321 /// distant light source with specified direction
322 /// parameters: FilterOpGraphNode, surfaceScale, diffuseConstant,
323 /// kernelUnitLengthX, kernelUnitLengthY, azimuth, elevation
324 /// SVG filter semantics - selectable input(s), selectable between linear
325 /// (default) and sRGB color space for calculations
326 /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEDiffuseLightingElement
327 /// https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEDistantLightElement
328 SVGFEDiffuseLightingDistant{surface_scale: Au, diffuse_constant: Au,
329 kernel_unit_length_x: Au, kernel_unit_length_y: Au, azimuth: Au,
330 elevation: Au},
331 /// calculate lighting based on heightmap image with provided values for a
332 /// point light source at specified location
333 /// parameters: FilterOpGraphNode, surfaceScale, diffuseConstant,
334 /// kernelUnitLengthX, kernelUnitLengthY, x, y, z
335 /// SVG filter semantics - selectable input(s), selectable between linear
336 /// (default) and sRGB color space for calculations
337 /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEDiffuseLightingElement
338 /// https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEPointLightElement
339 SVGFEDiffuseLightingPoint{surface_scale: Au, diffuse_constant: Au,
340 kernel_unit_length_x: Au, kernel_unit_length_y: Au, x: Au, y: Au,
341 z: Au},
342 /// calculate lighting based on heightmap image with provided values for a
343 /// spot light source at specified location pointing at specified target
344 /// location with specified hotspot sharpness and cone angle
345 /// parameters: FilterOpGraphNode, surfaceScale, diffuseConstant,
346 /// kernelUnitLengthX, kernelUnitLengthY, x, y, z, pointsAtX, pointsAtY,
347 /// pointsAtZ, specularExponent, limitingConeAngle
348 /// SVG filter semantics - selectable input(s), selectable between linear
349 /// (default) and sRGB color space for calculations
350 /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEDiffuseLightingElement
351 /// https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFESpotLightElement
352 SVGFEDiffuseLightingSpot{surface_scale: Au, diffuse_constant: Au,
353 kernel_unit_length_x: Au, kernel_unit_length_y: Au, x: Au, y: Au, z: Au,
354 points_at_x: Au, points_at_y: Au, points_at_z: Au, cone_exponent: Au,
355 limiting_cone_angle: Au},
356 /// calculate a distorted version of first input image using offset values
357 /// from second input image at specified intensity
358 /// parameters: FilterOpGraphNode, scale, xChannelSelector, yChannelSelector
359 /// SVG filter semantics - selectable input(s), selectable between linear
360 /// (default) and sRGB color space for calculations
361 /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEDisplacementMapElement
362 SVGFEDisplacementMap{scale: Au, x_channel_selector: u32,
363 y_channel_selector: u32},
364 /// create and merge a dropshadow version of the specified image's alpha
365 /// channel with specified offset and blur radius
366 /// parameters: FilterOpGraphNode, flood_color, flood_opacity, dx, dy,
367 /// stdDeviationX, stdDeviationY
368 /// SVG filter semantics - selectable input(s), selectable between linear
369 /// (default) and sRGB color space for calculations
370 /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEDropShadowElement
371 SVGFEDropShadow{color: ColorU, dx: Au, dy: Au, std_deviation_x: Au,
372 std_deviation_y: Au},
373 /// synthesize a new image of specified size containing a solid color
374 /// parameters: FilterOpGraphNode, color
375 /// SVG filter semantics - selectable input(s), selectable between linear
376 /// (default) and sRGB color space for calculations
377 /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEFloodElement
378 SVGFEFlood{color: ColorU},
379 /// create a blurred version of the input image
380 /// parameters: FilterOpGraphNode, stdDeviationX, stdDeviationY
381 /// SVG filter semantics - selectable input(s), selectable between linear
382 /// (default) and sRGB color space for calculations
383 /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEGaussianBlurElement
384 SVGFEGaussianBlur{std_deviation_x: Au, std_deviation_y: Au},
385 /// Filter that does no transformation of the colors, needed for
386 /// debug purposes, and is the default value in impl_default_for_enums.
387 SVGFEIdentity,
388 /// synthesize a new image based on a url (i.e. blob image source)
389 /// parameters: FilterOpGraphNode, sampling_filter (see SamplingFilter in
390 /// Types.h), transform
391 /// SVG filter semantics - selectable input(s), selectable between linear
392 /// (default) and sRGB color space for calculations
393 /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEImageElement
394 SVGFEImage{sampling_filter: u32, matrix: [Au; 6]},
395 /// create a new image based on the input image with the contour stretched
396 /// outward (dilate operator)
397 /// parameters: FilterOpGraphNode, radiusX, radiusY
398 /// SVG filter semantics - selectable input(s), selectable between linear
399 /// (default) and sRGB color space for calculations
400 /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEMorphologyElement
401 SVGFEMorphologyDilate{radius_x: Au, radius_y: Au},
402 /// create a new image based on the input image with the contour shrunken
403 /// inward (erode operator)
404 /// parameters: FilterOpGraphNode, radiusX, radiusY
405 /// SVG filter semantics - selectable input(s), selectable between linear
406 /// (default) and sRGB color space for calculations
407 /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEMorphologyElement
408 SVGFEMorphologyErode{radius_x: Au, radius_y: Au},
409 /// represents CSS opacity property as a graph node like the rest of the
410 /// SVGFE* filters
411 /// parameters: FilterOpGraphNode
412 /// SVG filter semantics - selectable input(s), selectable between linear
413 /// (default) and sRGB color space for calculations
414 SVGFEOpacity{value: Au},
415 /// represents CSS opacity property as a graph node like the rest of the
416 /// SVGFE* filters
417 /// parameters: FilterOpGraphNode
418 /// SVG filter semantics - selectable input(s), selectable between linear
419 /// (default) and sRGB color space for calculations
420 SVGFEOpacityBinding{valuebindingid: PropertyBindingId, value: Au},
421 /// Filter that copies the SourceGraphic image into the specified subregion,
422 /// This is intentionally the only way to get SourceGraphic into the graph,
423 /// as the filter region must be applied before it is used.
424 /// parameters: FilterOpGraphNode
425 /// SVG filter semantics - no inputs, no linear
426 SVGFESourceGraphic,
427 /// Filter that copies the SourceAlpha image into the specified subregion,
428 /// This is intentionally the only way to get SourceAlpha into the graph,
429 /// as the filter region must be applied before it is used.
430 /// parameters: FilterOpGraphNode
431 /// SVG filter semantics - no inputs, no linear
432 SVGFESourceAlpha,
433 /// calculate lighting based on heightmap image with provided values for a
434 /// distant light source with specified direction
435 /// parameters: FilerData, surfaceScale, specularConstant, specularExponent,
436 /// kernelUnitLengthX, kernelUnitLengthY, azimuth, elevation
437 /// SVG filter semantics - selectable input(s), selectable between linear
438 /// (default) and sRGB color space for calculations
439 /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFESpecularLightingElement
440 /// https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEDistantLightElement
441 SVGFESpecularLightingDistant{surface_scale: Au, specular_constant: Au,
442 specular_exponent: Au, kernel_unit_length_x: Au,
443 kernel_unit_length_y: Au, azimuth: Au, elevation: Au},
444 /// calculate lighting based on heightmap image with provided values for a
445 /// point light source at specified location
446 /// parameters: FilterOpGraphNode, surfaceScale, specularConstant,
447 /// specularExponent, kernelUnitLengthX, kernelUnitLengthY, x, y, z
448 /// SVG filter semantics - selectable input(s), selectable between linear
449 /// (default) and sRGB color space for calculations
450 /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFESpecularLightingElement
451 /// https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEPointLightElement
452 SVGFESpecularLightingPoint{surface_scale: Au, specular_constant: Au,
453 specular_exponent: Au, kernel_unit_length_x: Au,
454 kernel_unit_length_y: Au, x: Au, y: Au, z: Au},
455 /// calculate lighting based on heightmap image with provided values for a
456 /// spot light source at specified location pointing at specified target
457 /// location with specified hotspot sharpness and cone angle
458 /// parameters: FilterOpGraphNode, surfaceScale, specularConstant,
459 /// specularExponent, kernelUnitLengthX, kernelUnitLengthY, x, y, z,
460 /// pointsAtX, pointsAtY, pointsAtZ, specularExponent, limitingConeAngle
461 /// SVG filter semantics - selectable input(s), selectable between linear
462 /// (default) and sRGB color space for calculations
463 /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFESpecularLightingElement
464 /// https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFESpotLightElement
465 SVGFESpecularLightingSpot{surface_scale: Au, specular_constant: Au,
466 specular_exponent: Au, kernel_unit_length_x: Au,
467 kernel_unit_length_y: Au, x: Au, y: Au, z: Au, points_at_x: Au,
468 points_at_y: Au, points_at_z: Au, cone_exponent: Au,
469 limiting_cone_angle: Au},
470 /// create a new image based on the input image, repeated throughout the
471 /// output rectangle
472 /// parameters: FilterOpGraphNode
473 /// SVG filter semantics - selectable input(s), selectable between linear
474 /// (default) and sRGB color space for calculations
475 /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFETileElement
476 SVGFETile,
477 /// convert a color image to an alpha channel - internal use; generated by
478 /// SVGFilterInstance::GetOrCreateSourceAlphaIndex().
479 SVGFEToAlpha,
480 /// synthesize a new image based on Fractal Noise (Perlin) with the chosen
481 /// stitching mode
482 /// parameters: FilterOpGraphNode, baseFrequencyX, baseFrequencyY,
483 /// numOctaves, seed
484 /// SVG filter semantics - selectable input(s), selectable between linear
485 /// (default) and sRGB color space for calculations
486 /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFETurbulenceElement
487 SVGFETurbulenceWithFractalNoiseWithNoStitching{base_frequency_x: Au,
488 base_frequency_y: Au, num_octaves: u32, seed: u32},
489 /// synthesize a new image based on Fractal Noise (Perlin) with the chosen
490 /// stitching mode
491 /// parameters: FilterOpGraphNode, baseFrequencyX, baseFrequencyY,
492 /// numOctaves, seed
493 /// SVG filter semantics - selectable input(s), selectable between linear
494 /// (default) and sRGB color space for calculations
495 /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFETurbulenceElement
496 SVGFETurbulenceWithFractalNoiseWithStitching{base_frequency_x: Au,
497 base_frequency_y: Au, num_octaves: u32, seed: u32},
498 /// synthesize a new image based on Turbulence Noise (offset vectors)
499 /// parameters: FilterOpGraphNode, baseFrequencyX, baseFrequencyY,
500 /// numOctaves, seed
501 /// SVG filter semantics - selectable input(s), selectable between linear
502 /// (default) and sRGB color space for calculations
503 /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFETurbulenceElement
504 SVGFETurbulenceWithTurbulenceNoiseWithNoStitching{base_frequency_x: Au,
505 base_frequency_y: Au, num_octaves: u32, seed: u32},
506 /// synthesize a new image based on Turbulence Noise (offset vectors)
507 /// parameters: FilterOpGraphNode, baseFrequencyX, baseFrequencyY,
508 /// numOctaves, seed
509 /// SVG filter semantics - selectable input(s), selectable between linear
510 /// (default) and sRGB color space for calculations
511 /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFETurbulenceElement
512 SVGFETurbulenceWithTurbulenceNoiseWithStitching{base_frequency_x: Au,
513 base_frequency_y: Au, num_octaves: u32, seed: u32},
514}
515
516impl From<FilterGraphOp> for FilterGraphOpKey {
517 fn from(op: FilterGraphOp) -> Self {
518 match op {
519 FilterGraphOp::SVGFEBlendDarken => FilterGraphOpKey::SVGFEBlendDarken,
520 FilterGraphOp::SVGFEBlendLighten => FilterGraphOpKey::SVGFEBlendLighten,
521 FilterGraphOp::SVGFEBlendMultiply => FilterGraphOpKey::SVGFEBlendMultiply,
522 FilterGraphOp::SVGFEBlendNormal => FilterGraphOpKey::SVGFEBlendNormal,
523 FilterGraphOp::SVGFEBlendScreen => FilterGraphOpKey::SVGFEBlendScreen,
524 FilterGraphOp::SVGFEBlendOverlay => FilterGraphOpKey::SVGFEBlendOverlay,
525 FilterGraphOp::SVGFEBlendColorDodge => FilterGraphOpKey::SVGFEBlendColorDodge,
526 FilterGraphOp::SVGFEBlendColorBurn => FilterGraphOpKey::SVGFEBlendColorBurn,
527 FilterGraphOp::SVGFEBlendHardLight => FilterGraphOpKey::SVGFEBlendHardLight,
528 FilterGraphOp::SVGFEBlendSoftLight => FilterGraphOpKey::SVGFEBlendSoftLight,
529 FilterGraphOp::SVGFEBlendDifference => FilterGraphOpKey::SVGFEBlendDifference,
530 FilterGraphOp::SVGFEBlendExclusion => FilterGraphOpKey::SVGFEBlendExclusion,
531 FilterGraphOp::SVGFEBlendHue => FilterGraphOpKey::SVGFEBlendHue,
532 FilterGraphOp::SVGFEBlendSaturation => FilterGraphOpKey::SVGFEBlendSaturation,
533 FilterGraphOp::SVGFEBlendColor => FilterGraphOpKey::SVGFEBlendColor,
534 FilterGraphOp::SVGFEBlendLuminosity => FilterGraphOpKey::SVGFEBlendLuminosity,
535 FilterGraphOp::SVGFEColorMatrix { values: color_matrix } => {
536 let mut quantized_values: [Au; 20] = [Au(0); 20];
537 for (value, result) in color_matrix.iter().zip(quantized_values.iter_mut()) {
538 *result = Au::from_f32_px(*value);
539 }
540 FilterGraphOpKey::SVGFEColorMatrix{values: quantized_values}
541 }
542 FilterGraphOp::SVGFEComponentTransfer => unreachable!(),
543 FilterGraphOp::SVGFEComponentTransferInterned { handle, creates_pixels } => FilterGraphOpKey::SVGFEComponentTransferInterned{
544 handle: handle.uid(),
545 creates_pixels,
546 },
547 FilterGraphOp::SVGFECompositeArithmetic { k1, k2, k3, k4 } => {
548 FilterGraphOpKey::SVGFECompositeArithmetic{
549 k1: Au::from_f32_px(k1),
550 k2: Au::from_f32_px(k2),
551 k3: Au::from_f32_px(k3),
552 k4: Au::from_f32_px(k4),
553 }
554 }
555 FilterGraphOp::SVGFECompositeATop => FilterGraphOpKey::SVGFECompositeATop,
556 FilterGraphOp::SVGFECompositeIn => FilterGraphOpKey::SVGFECompositeIn,
557 FilterGraphOp::SVGFECompositeLighter => FilterGraphOpKey::SVGFECompositeLighter,
558 FilterGraphOp::SVGFECompositeOut => FilterGraphOpKey::SVGFECompositeOut,
559 FilterGraphOp::SVGFECompositeOver => FilterGraphOpKey::SVGFECompositeOver,
560 FilterGraphOp::SVGFECompositeXOR => FilterGraphOpKey::SVGFECompositeXOR,
561 FilterGraphOp::SVGFEConvolveMatrixEdgeModeDuplicate { order_x, order_y, kernel, divisor, bias, target_x, target_y, kernel_unit_length_x, kernel_unit_length_y, preserve_alpha } => {
562 let mut values: [Au; SVGFE_CONVOLVE_VALUES_LIMIT] = [Au(0); SVGFE_CONVOLVE_VALUES_LIMIT];
563 for (value, result) in kernel.iter().zip(values.iter_mut()) {
564 *result = Au::from_f32_px(*value)
565 }
566 FilterGraphOpKey::SVGFEConvolveMatrixEdgeModeDuplicate{
567 order_x,
568 order_y,
569 kernel: values,
570 divisor: Au::from_f32_px(divisor),
571 bias: Au::from_f32_px(bias),
572 target_x,
573 target_y,
574 kernel_unit_length_x: Au::from_f32_px(kernel_unit_length_x),
575 kernel_unit_length_y: Au::from_f32_px(kernel_unit_length_y),
576 preserve_alpha,
577 }
578 }
579 FilterGraphOp::SVGFEConvolveMatrixEdgeModeNone { order_x, order_y, kernel, divisor, bias, target_x, target_y, kernel_unit_length_x, kernel_unit_length_y, preserve_alpha } => {
580 let mut values: [Au; SVGFE_CONVOLVE_VALUES_LIMIT] = [Au(0); SVGFE_CONVOLVE_VALUES_LIMIT];
581 for (value, result) in kernel.iter().zip(values.iter_mut()) {
582 *result = Au::from_f32_px(*value)
583 }
584 FilterGraphOpKey::SVGFEConvolveMatrixEdgeModeNone{
585 order_x,
586 order_y,
587 kernel: values,
588 divisor: Au::from_f32_px(divisor),
589 bias: Au::from_f32_px(bias),
590 target_x,
591 target_y,
592 kernel_unit_length_x: Au::from_f32_px(kernel_unit_length_x),
593 kernel_unit_length_y: Au::from_f32_px(kernel_unit_length_y),
594 preserve_alpha,
595 }
596 }
597 FilterGraphOp::SVGFEConvolveMatrixEdgeModeWrap { order_x, order_y, kernel, divisor, bias, target_x, target_y, kernel_unit_length_x, kernel_unit_length_y, preserve_alpha } => {
598 let mut values: [Au; SVGFE_CONVOLVE_VALUES_LIMIT] = [Au(0); SVGFE_CONVOLVE_VALUES_LIMIT];
599 for (value, result) in kernel.iter().zip(values.iter_mut()) {
600 *result = Au::from_f32_px(*value)
601 }
602 FilterGraphOpKey::SVGFEConvolveMatrixEdgeModeWrap{
603 order_x,
604 order_y,
605 kernel: values,
606 divisor: Au::from_f32_px(divisor),
607 bias: Au::from_f32_px(bias),
608 target_x,
609 target_y,
610 kernel_unit_length_x: Au::from_f32_px(kernel_unit_length_x),
611 kernel_unit_length_y: Au::from_f32_px(kernel_unit_length_y),
612 preserve_alpha,
613 }
614 }
615 FilterGraphOp::SVGFEDiffuseLightingDistant { surface_scale, diffuse_constant, kernel_unit_length_x, kernel_unit_length_y, azimuth, elevation } => {
616 FilterGraphOpKey::SVGFEDiffuseLightingDistant{
617 surface_scale: Au::from_f32_px(surface_scale),
618 diffuse_constant: Au::from_f32_px(diffuse_constant),
619 kernel_unit_length_x: Au::from_f32_px(kernel_unit_length_x),
620 kernel_unit_length_y: Au::from_f32_px(kernel_unit_length_y),
621 azimuth: Au::from_f32_px(azimuth),
622 elevation: Au::from_f32_px(elevation),
623 }
624 }
625 FilterGraphOp::SVGFEDiffuseLightingPoint { surface_scale, diffuse_constant, kernel_unit_length_x, kernel_unit_length_y, x, y, z } => {
626 FilterGraphOpKey::SVGFEDiffuseLightingPoint{
627 surface_scale: Au::from_f32_px(surface_scale),
628 diffuse_constant: Au::from_f32_px(diffuse_constant),
629 kernel_unit_length_x: Au::from_f32_px(kernel_unit_length_x),
630 kernel_unit_length_y: Au::from_f32_px(kernel_unit_length_y),
631 x: Au::from_f32_px(x),
632 y: Au::from_f32_px(y),
633 z: Au::from_f32_px(z),
634 }
635 }
636 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 } => {
637 FilterGraphOpKey::SVGFEDiffuseLightingSpot{
638 surface_scale: Au::from_f32_px(surface_scale),
639 diffuse_constant: Au::from_f32_px(diffuse_constant),
640 kernel_unit_length_x: Au::from_f32_px(kernel_unit_length_x),
641 kernel_unit_length_y: Au::from_f32_px(kernel_unit_length_y),
642 x: Au::from_f32_px(x),
643 y: Au::from_f32_px(y),
644 z: Au::from_f32_px(z),
645 points_at_x: Au::from_f32_px(points_at_x),
646 points_at_y: Au::from_f32_px(points_at_y),
647 points_at_z: Au::from_f32_px(points_at_z),
648 cone_exponent: Au::from_f32_px(cone_exponent),
649 limiting_cone_angle: Au::from_f32_px(limiting_cone_angle),
650 }
651 }
652 FilterGraphOp::SVGFEDisplacementMap { scale, x_channel_selector, y_channel_selector } => {
653 FilterGraphOpKey::SVGFEDisplacementMap{
654 scale: Au::from_f32_px(scale),
655 x_channel_selector,
656 y_channel_selector,
657 }
658 }
659 FilterGraphOp::SVGFEDropShadow { color, dx, dy, std_deviation_x, std_deviation_y } => {
660 FilterGraphOpKey::SVGFEDropShadow{
661 color: color.into(),
662 dx: Au::from_f32_px(dx),
663 dy: Au::from_f32_px(dy),
664 std_deviation_x: Au::from_f32_px(std_deviation_x),
665 std_deviation_y: Au::from_f32_px(std_deviation_y),
666 }
667 }
668 FilterGraphOp::SVGFEFlood { color } => FilterGraphOpKey::SVGFEFlood{color: color.into()},
669 FilterGraphOp::SVGFEGaussianBlur { std_deviation_x, std_deviation_y } => {
670 FilterGraphOpKey::SVGFEGaussianBlur{
671 std_deviation_x: Au::from_f32_px(std_deviation_x),
672 std_deviation_y: Au::from_f32_px(std_deviation_y),
673 }
674 }
675 FilterGraphOp::SVGFEIdentity => FilterGraphOpKey::SVGFEIdentity,
676 FilterGraphOp::SVGFEImage { sampling_filter, matrix } => {
677 let mut values: [Au; 6] = [Au(0); 6];
678 for (value, result) in matrix.iter().zip(values.iter_mut()) {
679 *result = Au::from_f32_px(*value)
680 }
681 FilterGraphOpKey::SVGFEImage{
682 sampling_filter,
683 matrix: values,
684 }
685 }
686 FilterGraphOp::SVGFEMorphologyDilate { radius_x, radius_y } => {
687 FilterGraphOpKey::SVGFEMorphologyDilate{
688 radius_x: Au::from_f32_px(radius_x),
689 radius_y: Au::from_f32_px(radius_y),
690 }
691 }
692 FilterGraphOp::SVGFEMorphologyErode { radius_x, radius_y } => {
693 FilterGraphOpKey::SVGFEMorphologyErode{
694 radius_x: Au::from_f32_px(radius_x),
695 radius_y: Au::from_f32_px(radius_y),
696 }
697 }
698 FilterGraphOp::SVGFEOpacity{valuebinding: binding, value: _} => {
699 match binding {
700 PropertyBinding::Value(value) => {
701 FilterGraphOpKey::SVGFEOpacity{value: Au::from_f32_px(value)}
702 }
703 PropertyBinding::Binding(key, default) => {
704 FilterGraphOpKey::SVGFEOpacityBinding{valuebindingid: key.id, value: Au::from_f32_px(default)}
705 }
706 }
707 }
708 FilterGraphOp::SVGFESourceAlpha => FilterGraphOpKey::SVGFESourceAlpha,
709 FilterGraphOp::SVGFESourceGraphic => FilterGraphOpKey::SVGFESourceGraphic,
710 FilterGraphOp::SVGFESpecularLightingDistant { surface_scale, specular_constant, specular_exponent, kernel_unit_length_x, kernel_unit_length_y, azimuth, elevation } => {
711 FilterGraphOpKey::SVGFESpecularLightingDistant{
712 surface_scale: Au::from_f32_px(surface_scale),
713 specular_constant: Au::from_f32_px(specular_constant),
714 specular_exponent: Au::from_f32_px(specular_exponent),
715 kernel_unit_length_x: Au::from_f32_px(kernel_unit_length_x),
716 kernel_unit_length_y: Au::from_f32_px(kernel_unit_length_y),
717 azimuth: Au::from_f32_px(azimuth),
718 elevation: Au::from_f32_px(elevation),
719 }
720 }
721 FilterGraphOp::SVGFESpecularLightingPoint { surface_scale, specular_constant, specular_exponent, kernel_unit_length_x, kernel_unit_length_y, x, y, z } => {
722 FilterGraphOpKey::SVGFESpecularLightingPoint{
723 surface_scale: Au::from_f32_px(surface_scale),
724 specular_constant: Au::from_f32_px(specular_constant),
725 specular_exponent: Au::from_f32_px(specular_exponent),
726 kernel_unit_length_x: Au::from_f32_px(kernel_unit_length_x),
727 kernel_unit_length_y: Au::from_f32_px(kernel_unit_length_y),
728 x: Au::from_f32_px(x),
729 y: Au::from_f32_px(y),
730 z: Au::from_f32_px(z),
731 }
732 }
733 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 } => {
734 FilterGraphOpKey::SVGFESpecularLightingSpot{
735 surface_scale: Au::from_f32_px(surface_scale),
736 specular_constant: Au::from_f32_px(specular_constant),
737 specular_exponent: Au::from_f32_px(specular_exponent),
738 kernel_unit_length_x: Au::from_f32_px(kernel_unit_length_x),
739 kernel_unit_length_y: Au::from_f32_px(kernel_unit_length_y),
740 x: Au::from_f32_px(x),
741 y: Au::from_f32_px(y),
742 z: Au::from_f32_px(z),
743 points_at_x: Au::from_f32_px(points_at_x),
744 points_at_y: Au::from_f32_px(points_at_y),
745 points_at_z: Au::from_f32_px(points_at_z),
746 cone_exponent: Au::from_f32_px(cone_exponent),
747 limiting_cone_angle: Au::from_f32_px(limiting_cone_angle),
748 }
749 }
750 FilterGraphOp::SVGFETile => FilterGraphOpKey::SVGFETile,
751 FilterGraphOp::SVGFEToAlpha => FilterGraphOpKey::SVGFEToAlpha,
752 FilterGraphOp::SVGFETurbulenceWithFractalNoiseWithNoStitching { base_frequency_x, base_frequency_y, num_octaves, seed } => {
753 FilterGraphOpKey::SVGFETurbulenceWithFractalNoiseWithNoStitching {
754 base_frequency_x: Au::from_f32_px(base_frequency_x),
755 base_frequency_y: Au::from_f32_px(base_frequency_y),
756 num_octaves,
757 seed,
758 }
759 }
760 FilterGraphOp::SVGFETurbulenceWithFractalNoiseWithStitching { base_frequency_x, base_frequency_y, num_octaves, seed } => {
761 FilterGraphOpKey::SVGFETurbulenceWithFractalNoiseWithStitching {
762 base_frequency_x: Au::from_f32_px(base_frequency_x),
763 base_frequency_y: Au::from_f32_px(base_frequency_y),
764 num_octaves,
765 seed,
766 }
767 }
768 FilterGraphOp::SVGFETurbulenceWithTurbulenceNoiseWithNoStitching { base_frequency_x, base_frequency_y, num_octaves, seed } => {
769 FilterGraphOpKey::SVGFETurbulenceWithTurbulenceNoiseWithNoStitching {
770 base_frequency_x: Au::from_f32_px(base_frequency_x),
771 base_frequency_y: Au::from_f32_px(base_frequency_y),
772 num_octaves,
773 seed,
774 }
775 }
776 FilterGraphOp::SVGFETurbulenceWithTurbulenceNoiseWithStitching { base_frequency_x, base_frequency_y, num_octaves, seed } => {
777 FilterGraphOpKey::SVGFETurbulenceWithTurbulenceNoiseWithStitching {
778 base_frequency_x: Au::from_f32_px(base_frequency_x),
779 base_frequency_y: Au::from_f32_px(base_frequency_y),
780 num_octaves,
781 seed,
782 }
783 }
784 }
785 }
786}
787
788#[cfg_attr(feature = "capture", derive(Serialize))]
789#[cfg_attr(feature = "replay", derive(Deserialize))]
790#[derive(Debug, Clone, MallocSizeOf, PartialEq, Hash, Eq)]
791pub struct FilterGraphNodeKey {
792 /// Indicates this graph node was marked as unnecessary by the DAG optimizer
793 /// (for example SVGFEOffset can often be folded into downstream nodes)
794 pub kept_by_optimizer: bool,
795 /// True if color_interpolation_filter == LinearRgb; shader will convert
796 /// sRGB texture pixel colors on load and convert back on store, for correct
797 /// interpolation
798 pub linear: bool,
799 /// virtualized picture input binding 1 (i.e. texture source), typically
800 /// this is used, but certain filters do not use it
801 pub inputs: Vec<FilterGraphPictureReferenceKey>,
802 /// rect this node will render into, in filter space, does not account for
803 /// inflate or device_pixel_scale
804 pub subregion: [Au; 4],
805}
806
807impl From<FilterGraphNode> for FilterGraphNodeKey {
808 fn from(node: FilterGraphNode) -> Self {
809 FilterGraphNodeKey{
810 kept_by_optimizer: node.kept_by_optimizer,
811 linear: node.linear,
812 inputs: node.inputs.into_iter().map(|node| {node.into()}).collect(),
813 subregion: [
814 Au::from_f32_px(node.subregion.min.x),
815 Au::from_f32_px(node.subregion.min.y),
816 Au::from_f32_px(node.subregion.max.x),
817 Au::from_f32_px(node.subregion.max.y),
818 ],
819 }
820 }
821}
822
823/// Represents a hashable description of how a picture primitive
824/// will be composited into its parent.
825#[cfg_attr(feature = "capture", derive(Serialize))]
826#[cfg_attr(feature = "replay", derive(Deserialize))]
827#[derive(Debug, Clone, MallocSizeOf, PartialEq, Hash, Eq)]
828pub enum PictureCompositeKey {
829 // No visual compositing effect
830 Identity,
831
832 // FilterOp
833 Blur(Au, Au, bool, BlurEdgeMode),
834 Brightness(Au),
835 Contrast(Au),
836 Grayscale(Au),
837 HueRotate(Au),
838 Invert(Au),
839 Opacity(Au),
840 OpacityBinding(PropertyBindingId, Au),
841 Saturate(Au),
842 Sepia(Au),
843 DropShadows(Vec<(VectorKey, Au, ColorU)>),
844 ColorMatrix([Au; 20]),
845 SrgbToLinear,
846 LinearToSrgb,
847 ComponentTransfer(ItemUid),
848 Flood(ColorU),
849 SvgFilter(Vec<FilterPrimitiveKey>),
850 SVGFEGraph(Vec<(FilterGraphNodeKey, FilterGraphOpKey)>),
851
852 // MixBlendMode
853 Multiply,
854 Screen,
855 Overlay,
856 Darken,
857 Lighten,
858 ColorDodge,
859 ColorBurn,
860 HardLight,
861 SoftLight,
862 Difference,
863 Exclusion,
864 Hue,
865 Saturation,
866 Color,
867 Luminosity,
868 PlusLighter,
869}
870
871impl From<Option<PictureCompositeMode>> for PictureCompositeKey {
872 fn from(mode: Option<PictureCompositeMode>) -> Self {
873 match mode {
874 Some(PictureCompositeMode::MixBlend(mode)) => {
875 match mode {
876 MixBlendMode::Normal => PictureCompositeKey::Identity,
877 MixBlendMode::Multiply => PictureCompositeKey::Multiply,
878 MixBlendMode::Screen => PictureCompositeKey::Screen,
879 MixBlendMode::Overlay => PictureCompositeKey::Overlay,
880 MixBlendMode::Darken => PictureCompositeKey::Darken,
881 MixBlendMode::Lighten => PictureCompositeKey::Lighten,
882 MixBlendMode::ColorDodge => PictureCompositeKey::ColorDodge,
883 MixBlendMode::ColorBurn => PictureCompositeKey::ColorBurn,
884 MixBlendMode::HardLight => PictureCompositeKey::HardLight,
885 MixBlendMode::SoftLight => PictureCompositeKey::SoftLight,
886 MixBlendMode::Difference => PictureCompositeKey::Difference,
887 MixBlendMode::Exclusion => PictureCompositeKey::Exclusion,
888 MixBlendMode::Hue => PictureCompositeKey::Hue,
889 MixBlendMode::Saturation => PictureCompositeKey::Saturation,
890 MixBlendMode::Color => PictureCompositeKey::Color,
891 MixBlendMode::Luminosity => PictureCompositeKey::Luminosity,
892 MixBlendMode::PlusLighter => PictureCompositeKey::PlusLighter,
893 }
894 }
895 Some(PictureCompositeMode::Filter(op)) => {
896 match op {
897 Filter::Blur { width, height, should_inflate, edge_mode } => {
898 PictureCompositeKey::Blur(
899 Au::from_f32_px(width),
900 Au::from_f32_px(height),
901 should_inflate,
902 edge_mode,
903 )
904 }
905 Filter::Brightness(value) => PictureCompositeKey::Brightness(Au::from_f32_px(value)),
906 Filter::Contrast(value) => PictureCompositeKey::Contrast(Au::from_f32_px(value)),
907 Filter::Grayscale(value) => PictureCompositeKey::Grayscale(Au::from_f32_px(value)),
908 Filter::HueRotate(value) => PictureCompositeKey::HueRotate(Au::from_f32_px(value)),
909 Filter::Invert(value) => PictureCompositeKey::Invert(Au::from_f32_px(value)),
910 Filter::Saturate(value) => PictureCompositeKey::Saturate(Au::from_f32_px(value)),
911 Filter::Sepia(value) => PictureCompositeKey::Sepia(Au::from_f32_px(value)),
912 Filter::SrgbToLinear => PictureCompositeKey::SrgbToLinear,
913 Filter::LinearToSrgb => PictureCompositeKey::LinearToSrgb,
914 Filter::Identity => PictureCompositeKey::Identity,
915 Filter::DropShadows(ref shadows) => {
916 PictureCompositeKey::DropShadows(
917 shadows.iter().map(|shadow| {
918 (shadow.offset.into(), Au::from_f32_px(shadow.blur_radius), shadow.color.into())
919 }).collect()
920 )
921 }
922 Filter::Opacity(binding, _) => {
923 match binding {
924 PropertyBinding::Value(value) => {
925 PictureCompositeKey::Opacity(Au::from_f32_px(value))
926 }
927 PropertyBinding::Binding(key, default) => {
928 PictureCompositeKey::OpacityBinding(key.id, Au::from_f32_px(default))
929 }
930 }
931 }
932 Filter::ColorMatrix(values) => {
933 let mut quantized_values: [Au; 20] = [Au(0); 20];
934 for (value, result) in values.iter().zip(quantized_values.iter_mut()) {
935 *result = Au::from_f32_px(*value);
936 }
937 PictureCompositeKey::ColorMatrix(quantized_values)
938 }
939 Filter::ComponentTransfer => unreachable!(),
940 Filter::Flood(color) => PictureCompositeKey::Flood(color.into()),
941 Filter::SVGGraphNode(_node, _op) => unreachable!(),
942 }
943 }
944 Some(PictureCompositeMode::ComponentTransferFilter(handle)) => {
945 PictureCompositeKey::ComponentTransfer(handle.uid())
946 }
947 Some(PictureCompositeMode::SvgFilter(filter_primitives, filter_data)) => {
948 PictureCompositeKey::SvgFilter(filter_primitives.into_iter().map(|primitive| {
949 match primitive.kind {
950 FilterPrimitiveKind::Identity(identity) => FilterPrimitiveKey::Identity(primitive.color_space, identity.input),
951 FilterPrimitiveKind::Blend(blend) => FilterPrimitiveKey::Blend(primitive.color_space, blend.mode, blend.input1, blend.input2),
952 FilterPrimitiveKind::Flood(flood) => FilterPrimitiveKey::Flood(primitive.color_space, flood.color.into()),
953 FilterPrimitiveKind::Blur(blur) =>
954 FilterPrimitiveKey::Blur(primitive.color_space, Au::from_f32_px(blur.width), Au::from_f32_px(blur.height), blur.input),
955 FilterPrimitiveKind::Opacity(opacity) =>
956 FilterPrimitiveKey::Opacity(primitive.color_space, Au::from_f32_px(opacity.opacity), opacity.input),
957 FilterPrimitiveKind::ColorMatrix(color_matrix) => {
958 let mut quantized_values: [Au; 20] = [Au(0); 20];
959 for (value, result) in color_matrix.matrix.iter().zip(quantized_values.iter_mut()) {
960 *result = Au::from_f32_px(*value);
961 }
962 FilterPrimitiveKey::ColorMatrix(primitive.color_space, quantized_values, color_matrix.input)
963 }
964 FilterPrimitiveKind::DropShadow(drop_shadow) => {
965 FilterPrimitiveKey::DropShadow(
966 primitive.color_space,
967 (
968 drop_shadow.shadow.offset.into(),
969 Au::from_f32_px(drop_shadow.shadow.blur_radius),
970 drop_shadow.shadow.color.into(),
971 ),
972 drop_shadow.input,
973 )
974 }
975 FilterPrimitiveKind::ComponentTransfer(component_transfer) =>
976 FilterPrimitiveKey::ComponentTransfer(primitive.color_space, component_transfer.input, filter_data.clone()),
977 FilterPrimitiveKind::Offset(info) =>
978 FilterPrimitiveKey::Offset(primitive.color_space, info.input, info.offset.into()),
979 FilterPrimitiveKind::Composite(info) =>
980 FilterPrimitiveKey::Composite(primitive.color_space, info.input1, info.input2, info.operator.into()),
981 }
982 }).collect())
983 }
984 Some(PictureCompositeMode::SVGFEGraph(filter_nodes)) => {
985 PictureCompositeKey::SVGFEGraph(
986 filter_nodes.into_iter().map(|(node, op)| {
987 (node.into(), op.into())
988 }).collect())
989 }
990 Some(PictureCompositeMode::Blit(_)) |
991 Some(PictureCompositeMode::TileCache { .. }) |
992 Some(PictureCompositeMode::IntermediateSurface) |
993 None => {
994 PictureCompositeKey::Identity
995 }
996 }
997 }
998}
999
1000#[cfg_attr(feature = "capture", derive(Serialize))]
1001#[cfg_attr(feature = "replay", derive(Deserialize))]
1002#[derive(Debug, Clone, Eq, MallocSizeOf, PartialEq, Hash)]
1003pub struct Picture {
1004 pub composite_mode_key: PictureCompositeKey,
1005 pub raster_space: RasterSpace,
1006}
1007
1008#[cfg_attr(feature = "capture", derive(Serialize))]
1009#[cfg_attr(feature = "replay", derive(Deserialize))]
1010#[derive(Debug, Clone, Eq, MallocSizeOf, PartialEq, Hash)]
1011pub struct PictureKey {
1012 pub composite_mode_key: PictureCompositeKey,
1013 pub raster_space: RasterSpace,
1014}
1015
1016impl PictureKey {
1017 pub fn new(
1018 pic: Picture,
1019 ) -> Self {
1020 PictureKey {
1021 composite_mode_key: pic.composite_mode_key,
1022 raster_space: pic.raster_space,
1023 }
1024 }
1025}
1026
1027impl InternDebug for PictureKey {}
1028
1029#[cfg_attr(feature = "capture", derive(Serialize))]
1030#[cfg_attr(feature = "replay", derive(Deserialize))]
1031#[derive(MallocSizeOf)]
1032pub struct PictureTemplate;
1033
1034impl From<PictureKey> for PictureTemplate {
1035 fn from(_: PictureKey) -> Self {
1036 PictureTemplate
1037 }
1038}
1039
1040pub type PictureDataHandle = InternHandle<Picture>;
1041
1042impl Internable for Picture {
1043 type Key = PictureKey;
1044 type StoreData = PictureTemplate;
1045 type InternData = ();
1046 const PROFILE_COUNTER: usize = crate::profiler::INTERNED_PICTURES;
1047}
1048
1049impl InternablePrimitive for Picture {
1050 fn into_key(
1051 self,
1052 _: &LayoutPrimitiveInfo,
1053 ) -> PictureKey {
1054 PictureKey::new(self)
1055 }
1056
1057 fn make_instance_kind(
1058 _key: PictureKey,
1059 _: PictureDataHandle,
1060 _: &mut PrimitiveStore,
1061 ) -> PrimitiveInstanceKind {
1062 // Should never be hit as this method should not be
1063 // called for pictures.
1064 unreachable!();
1065 }
1066}
1067
1068impl IsVisible for Picture {
1069 fn is_visible(&self) -> bool {
1070 true
1071 }
1072}
1073
1074#[test]
1075#[cfg(target_pointer_width = "64")]
1076fn test_struct_sizes() {
1077 use std::mem;
1078 // The sizes of these structures are critical for performance on a number of
1079 // talos stress tests. If you get a failure here on CI, there's two possibilities:
1080 // (a) You made a structure smaller than it currently is. Great work! Update the
1081 // test expectations and move on.
1082 // (b) You made a structure larger. This is not necessarily a problem, but should only
1083 // be done with care, and after checking if talos performance regresses badly.
1084 assert_eq!(mem::size_of::<Picture>(), 96, "Picture size changed");
1085 assert_eq!(mem::size_of::<PictureTemplate>(), 0, "PictureTemplate size changed");
1086 assert_eq!(mem::size_of::<PictureKey>(), 96, "PictureKey size changed");
1087}