Bug 1505871. Implement yaml reader/writer for component transfer. r=jrmuizel
☠☠ backed out by fe1872ed2a92 ☠ ☠
authorTimothy Nikkel <tnikkel@gmail.com>
Mon, 25 Feb 2019 22:45:16 -0600
changeset 461116 def812790f5c1d6d98bd4f0efab8ace51c7ff89e
parent 461115 90660632d6410ebb7e3530c048f04137d36b6587
child 461117 11c9d5a64a30a5b1c25056412162fe68a63fb83d
push id35618
push usershindli@mozilla.com
push dateTue, 26 Feb 2019 16:54:44 +0000
treeherdermozilla-central@d326a9d5f77b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjrmuizel
bugs1505871
milestone67.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1505871. Implement yaml reader/writer for component transfer. r=jrmuizel
gfx/wr/wrench/src/yaml_frame_reader.rs
gfx/wr/wrench/src/yaml_frame_writer.rs
gfx/wr/wrench/src/yaml_helper.rs
--- a/gfx/wr/wrench/src/yaml_frame_reader.rs
+++ b/gfx/wr/wrench/src/yaml_frame_reader.rs
@@ -1820,27 +1820,29 @@ impl YamlFrameReader {
         if is_root {
             if let Some(size) = yaml["scroll-offset"].as_point() {
                 let external_id = ExternalScrollId(0, dl.pipeline_id);
                 self.scroll_offsets.insert(external_id, LayoutPoint::new(size.x, size.y));
             }
         }
 
         let filters = yaml["filters"].as_vec_filter_op().unwrap_or(vec![]);
+        let filter_datas = yaml["filter-datas"].as_vec_filter_data().unwrap_or(vec![]);
 
         info.rect = bounds;
         info.clip_rect = bounds;
 
         dl.push_stacking_context(
             &info,
             *self.spatial_id_stack.last().unwrap(),
             clip_node_id,
             transform_style,
             mix_blend_mode,
             &filters,
+            &filter_datas,
             raster_space,
             cache_tiles,
         );
 
         if !yaml["items"].is_badvalue() {
             self.add_display_list_items_from_yaml(dl, wrench, &yaml["items"]);
         }
 
--- a/gfx/wr/wrench/src/yaml_frame_writer.rs
+++ b/gfx/wr/wrench/src/yaml_frame_writer.rs
@@ -212,16 +212,18 @@ fn write_reference_frame(
     usize_node(parent, "id", clip_id_mapper.add_spatial_id(reference_frame.id));
 }
 
 fn write_stacking_context(
     parent: &mut Table,
     sc: &StackingContext,
     properties: &SceneProperties,
     filter_iter: AuxIter<FilterOp>,
+    filter_data_iter: &[TempFilterData],
+    display_list: &BuiltDisplayList,
 ) {
     enum_node(parent, "transform-style", sc.transform_style);
 
     let raster_space = match sc.raster_space {
         RasterSpace::Local(scale) => {
             format!("local({})", scale)
         }
         RasterSpace::Screen => {
@@ -261,20 +263,60 @@ fn write_stacking_context(
                 filters.push(Yaml::String(format!("color-matrix({:?})", matrix)))
             }
             FilterOp::SrgbToLinear => {
                 filters.push(Yaml::String("srgb-to-linear".to_string()))
             }
             FilterOp::LinearToSrgb => {
                 filters.push(Yaml::String("linear-to-srgb".to_string()))
             }
+            FilterOp::ComponentTransfer => {
+                filters.push(Yaml::String("component-transfer".to_string()))
+            }
         }
     }
 
     yaml_node(parent, "filters", Yaml::Array(filters));
+
+    // filter datas
+    let mut filter_datas = vec![];
+    for filter_data in filter_data_iter {
+        let func_types = display_list.get(filter_data.func_types).map(|func_type| {
+            match func_type {
+                ComponentTransferFuncType::Identity => { Yaml::String("Identity".to_string()) }
+                ComponentTransferFuncType::Table => { Yaml::String("Table".to_string()) }
+                ComponentTransferFuncType::Discrete => { Yaml::String("Discrete".to_string()) }
+                ComponentTransferFuncType::Linear => { Yaml::String("Linear".to_string()) }
+                ComponentTransferFuncType::Gamma => { Yaml::String("Gamma".to_string()) }
+            }
+        }).collect();
+        let r_values = display_list.get(filter_data.r_values).map(|value| {
+            Yaml::String(format!("{}", value))
+        }).collect();
+        let g_values = display_list.get(filter_data.g_values).map(|value| {
+            Yaml::String(format!("{}", value))
+        }).collect();
+        let b_values = display_list.get(filter_data.b_values).map(|value| {
+            Yaml::String(format!("{}", value))
+        }).collect();
+        let a_values = display_list.get(filter_data.a_values).map(|value| {
+            Yaml::String(format!("{}", value))
+        }).collect();
+
+        let avec: Vec<Yaml> = [
+            Yaml::Array(func_types),
+            Yaml::Array(r_values),
+            Yaml::Array(g_values),
+            Yaml::Array(b_values),
+            Yaml::Array(a_values),
+        ].to_vec();
+        filter_datas.push(Yaml::Array(avec));
+    }
+
+    yaml_node(parent, "filter-datas", Yaml::Array(filter_datas));
 }
 
 #[cfg(target_os = "macos")]
 fn native_font_handle_to_yaml(
     rsrc: &mut ResourceGenerator,
     handle: &NativeFontHandle,
     parent: &mut yaml_rust::yaml::Hash,
     path_opt: &mut Option<PathBuf>,
@@ -1029,16 +1071,18 @@ impl YamlFrameWriter {
                 Sdi::PushStackingContext(item) => {
                     str_node(&mut v, "type", "stacking-context");
                     let filters = display_list.get(base.filters());
                     write_stacking_context(
                         &mut v,
                         &item.stacking_context,
                         &scene.properties,
                         filters,
+                        base.filter_datas(),
+                        display_list,
                     );
 
                     let mut sub_iter = base.sub_iter();
                     self.write_display_list(&mut v, display_list, scene, &mut sub_iter, clip_id_mapper);
                     continue_traversal = Some(sub_iter);
                 }
                 Sdi::PushReferenceFrame(item) => {
                     str_node(&mut v, "type", "reference-frame");
@@ -1147,16 +1191,18 @@ impl YamlFrameWriter {
                 Sdi::PopStackingContext => return,
 
                 Sdi::PopCacheMarker => return,
                 Sdi::PushCacheMarker(_) => {
                     str_node(&mut v, "type", "cache-marker");
                 }
 
                 Sdi::SetGradientStops => panic!("dummy item yielded?"),
+                Sdi::SetFilterOps => panic!("dummy item yielded?"),
+                Sdi::SetFilterData => panic!("dummy item yielded?"),
                 Sdi::PushShadow(shadow) => {
                     str_node(&mut v, "type", "shadow");
                     vector_node(&mut v, "offset", &shadow.offset);
                     color_node(&mut v, "color", shadow.color);
                     f32_node(&mut v, "blur-radius", shadow.blur_radius);
                 }
                 Sdi::PopAllShadows => {
                     str_node(&mut v, "type", "pop-all-shadows");
--- a/gfx/wr/wrench/src/yaml_helper.rs
+++ b/gfx/wr/wrench/src/yaml_helper.rs
@@ -31,16 +31,18 @@ pub trait YamlHelper {
     fn as_border_radius_component(&self) -> LayoutSize;
     fn as_border_radius(&self) -> Option<BorderRadius>;
     fn as_transform_style(&self) -> Option<TransformStyle>;
     fn as_raster_space(&self) -> Option<RasterSpace>;
     fn as_clip_mode(&self) -> Option<ClipMode>;
     fn as_mix_blend_mode(&self) -> Option<MixBlendMode>;
     fn as_filter_op(&self) -> Option<FilterOp>;
     fn as_vec_filter_op(&self) -> Option<Vec<FilterOp>>;
+    fn as_filter_data(&self) -> Option<FilterData>;
+    fn as_vec_filter_data(&self) -> Option<Vec<FilterData>>;
 }
 
 fn string_to_color(color: &str) -> Option<ColorF> {
     match color {
         "red" => Some(ColorF::new(1.0, 0.0, 0.0, 1.0)),
         "green" => Some(ColorF::new(0.0, 1.0, 0.0, 1.0)),
         "blue" => Some(ColorF::new(0.0, 0.0, 1.0, 1.0)),
         "white" => Some(ColorF::new(1.0, 1.0, 1.0, 1.0)),
@@ -134,16 +136,27 @@ define_string_enum!(
         Dotted = "dotted",
         Dashed = "dashed",
         Wavy = "wavy"
     ]
 );
 
 define_string_enum!(ClipMode, [Clip = "clip", ClipOut = "clip-out"]);
 
+define_string_enum!(
+    ComponentTransferFuncType,
+    [
+        Identity = "Identity",
+        Table = "Table",
+        Discrete = "Discrete",
+        Linear = "Linear",
+        Gamma = "Gamma"
+    ]
+);
+
 // Rotate around `axis` by `degrees` angle
 fn make_rotation(
     origin: &LayoutPoint,
     degrees: f32,
     axis_x: f32,
     axis_y: f32,
     axis_z: f32,
 ) -> LayoutTransform {
@@ -543,16 +556,19 @@ impl YamlHelper for Yaml {
     }
 
     fn as_filter_op(&self) -> Option<FilterOp> {
         if let Some(s) = self.as_str() {
             match parse_function(s) {
                 ("identity", _, _) => {
                     Some(FilterOp::Identity)
                 }
+                ("component-transfer", _, _) => {
+                    Some(FilterOp::ComponentTransfer)
+                }
                 ("blur", ref args, _) if args.len() == 1 => {
                     Some(FilterOp::Blur(args[0].parse().unwrap()))
                 }
                 ("brightness", ref args, _) if args.len() == 1 => {
                     Some(FilterOp::Brightness(args[0].parse().unwrap()))
                 }
                 ("contrast", ref args, _) if args.len() == 1 => {
                     Some(FilterOp::Contrast(args[0].parse().unwrap()))
@@ -601,9 +617,57 @@ impl YamlHelper for Yaml {
 
     fn as_vec_filter_op(&self) -> Option<Vec<FilterOp>> {
         if let Some(v) = self.as_vec() {
             Some(v.iter().map(|x| x.as_filter_op().unwrap()).collect())
         } else {
             self.as_filter_op().map(|op| vec![op])
         }
     }
+
+    fn as_filter_data(&self) -> Option<FilterData> {
+        // Parse an array with five entries. First entry is an array of func types (4).
+        // The remaining entries are arrays of floats.
+        if let Yaml::Array(ref array) = *self {
+            if array.len() != 5 {
+                panic!("Invalid filter data specified, base array doesn't have five entries: {:?}", self);
+            }
+            if let Some(func_types_p) = array[0].as_vec_string() {
+                if func_types_p.len() != 4 {
+                    panic!("Invalid filter data specified, func type array doesn't have five entries: {:?}", self);
+                }
+                let func_types: Vec<ComponentTransferFuncType> =
+                    func_types_p.into_iter().map(|x| { match StringEnum::from_str(&x) {
+                        Some(y) => y,
+                        None => panic!("Invalid filter data specified, invalid func type name: {:?}", self),
+                    }}).collect();
+                if let Some(r_values_p) = array[1].as_vec_f32() {
+                    if let Some(g_values_p) = array[2].as_vec_f32() {
+                        if let Some(b_values_p) = array[3].as_vec_f32() {
+                            if let Some(a_values_p) = array[4].as_vec_f32() {
+                                let filter_data = FilterData {
+                                    func_r_type: func_types[0],
+                                    r_values: r_values_p,
+                                    func_g_type: func_types[1],
+                                    g_values: g_values_p,
+                                    func_b_type: func_types[2],
+                                    b_values: b_values_p,
+                                    func_a_type: func_types[3],
+                                    a_values: a_values_p,
+                                };
+                                return Some(filter_data)
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        None
+    }
+
+    fn as_vec_filter_data(&self) -> Option<Vec<FilterData>> {
+        if let Some(v) = self.as_vec() {
+            Some(v.iter().map(|x| x.as_filter_data().unwrap()).collect())
+        } else {
+            self.as_filter_data().map(|data| vec![data])
+        }
+    }
 }