Bug 1505871. Implement yaml reader/writer for component transfer. r=jrmuizel
☠☠ backed out by 3c030119c0dc ☠ ☠
authorTimothy Nikkel <tnikkel@gmail.com>
Mon, 25 Feb 2019 19:20:27 -0600
changeset 461102 0fd8742fa66223b490880d6b759066d1e5532148
parent 461101 1899600a79855a892c9ec75216db20ad5e2b0c2e
child 461103 1ad20d485eca142b1c10fc640fe8240b95f2cffe
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])
+        }
+    }
 }