Bug 1587198. Wrench: Supported saving images with strides != width*bytes_per_pixel. r=kvark
authorJeff Muizelaar <jrmuizel@gmail.com>
Wed, 09 Oct 2019 18:58:08 +0000
changeset 497323 e2153ccf7c79774e7556bf12191215e6ae420367
parent 497322 614162937d31c10958f663393fdc53387401fbde
child 497324 686a306609ad01ed4749b40d97a2b5116055ef4e
push id36682
push userncsoregi@mozilla.com
push dateSat, 12 Oct 2019 09:52:03 +0000
treeherdermozilla-central@06ea2371f897 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskvark
bugs1587198
milestone71.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 1587198. Wrench: Supported saving images with strides != width*bytes_per_pixel. r=kvark Differential Revision: https://phabricator.services.mozilla.com/D48602
gfx/wr/webrender/src/capture.rs
gfx/wr/webrender/src/renderer.rs
gfx/wr/webrender/src/resource_cache.rs
--- a/gfx/wr/webrender/src/capture.rs
+++ b/gfx/wr/webrender/src/capture.rs
@@ -96,20 +96,34 @@ impl CaptureConfig {
         match ron::de::from_str(&string) {
             Ok(out) => Some(out),
             Err(e) => panic!("File {:?} deserialization failed: {:?}", name.as_ref(), e),
         }
     }
 
     #[cfg(feature = "png")]
     pub fn save_png(
-        path: PathBuf, size: DeviceIntSize, format: ImageFormat, data: &[u8],
+        path: PathBuf, size: DeviceIntSize, format: ImageFormat, stride: Option<i32>, data: &[u8],
     ) {
         use png::{BitDepth, ColorType, Encoder};
         use std::io::BufWriter;
+        use std::borrow::Cow;
+
+        // `png` expects
+        let data = match stride {
+            Some(stride) if stride != format.bytes_per_pixel() * size.width => {
+                let mut unstrided = Vec::new();
+                for y in 0..size.height {
+                    let start = (y * stride) as usize;
+                    unstrided.extend_from_slice(&data[start..start+(size.width * format.bytes_per_pixel()) as usize]);
+                }
+                Cow::from(unstrided)
+            }
+            _ => Cow::from(data),
+        };
 
         let color_type = match format {
             ImageFormat::RGBA8 => ColorType::RGBA,
             ImageFormat::BGRA8 => {
                 warn!("Unable to swizzle PNG of BGRA8 type");
                 ColorType::RGBA
             },
             ImageFormat::R8 => ColorType::Grayscale,
@@ -121,17 +135,17 @@ impl CaptureConfig {
         };
         let w = BufWriter::new(File::create(path).unwrap());
         let mut enc = Encoder::new(w, size.width as u32, size.height as u32);
         enc.set_color(color_type);
         enc.set_depth(BitDepth::Eight);
         enc
             .write_header()
             .unwrap()
-            .write_image_data(&data)
+            .write_image_data(&*data)
             .unwrap();
     }
 }
 
 /// An image that `ResourceCache` is unable to resolve during a capture.
 /// The image has to be transferred to `Renderer` and locked with the
 /// external image handler to get the actual contents and serialize them.
 #[derive(Deserialize, Serialize)]
--- a/gfx/wr/webrender/src/renderer.rs
+++ b/gfx/wr/webrender/src/renderer.rs
@@ -6107,16 +6107,17 @@ impl Renderer {
                         device.read_pixels_into(rect, ImageFormat::RGBA8, &mut png_data);
                         (&png_data, ImageFormat::RGBA8)
                     }
                     fm => (&data, fm),
                 };
                 CaptureConfig::save_png(
                     root.join(format!("textures/{}-{}.png", name, layer_id)),
                     rect_size, format,
+                    None,
                     data_ref,
                 );
             }
             device.read_pixels_into(rect, read_format, &mut data);
             file.write_all(&data)
                 .unwrap();
         }
 
@@ -6230,16 +6231,17 @@ impl Renderer {
                         .expect(&format!("Unable to create {}", short_path))
                         .write_all(&bytes)
                         .unwrap();
                     #[cfg(feature = "png")]
                     CaptureConfig::save_png(
                         config.root.join(&short_path).with_extension("png"),
                         def.descriptor.size,
                         def.descriptor.format,
+                        def.descriptor.stride,
                         &bytes,
                     );
                 }
                 let plain = PlainExternalImage {
                     data: short_path,
                     external: def.external,
                     uv: ext_image.uv,
                 };
--- a/gfx/wr/webrender/src/resource_cache.rs
+++ b/gfx/wr/webrender/src/resource_cache.rs
@@ -2112,16 +2112,17 @@ impl ResourceCache {
                         Entry::Vacant(e) => e,
                     };
 
                     #[cfg(feature = "png")]
                     CaptureConfig::save_png(
                         root.join(format!("images/{}.png", image_id)),
                         desc.size,
                         desc.format,
+                        desc.stride,
                         &arc,
                     );
                     let file_name = format!("{}.raw", image_id);
                     let short_path = format!("images/{}", file_name);
                     fs::File::create(path_images.join(file_name))
                         .expect(&format!("Unable to create {}", short_path))
                         .write_all(&*arc)
                         .unwrap();
@@ -2167,16 +2168,17 @@ impl ResourceCache {
                     assert_eq!(result.data.len(), desc.compute_total_size() as usize);
 
                     num_blobs += 1;
                     #[cfg(feature = "png")]
                     CaptureConfig::save_png(
                         root.join(format!("blobs/{}.png", num_blobs)),
                         desc.size,
                         desc.format,
+                        desc.stride,
                         &result.data,
                     );
                     let file_name = format!("{}.raw", num_blobs);
                     let short_path = format!("blobs/{}", file_name);
                     let full_path = path_blobs.clone().join(&file_name);
                     fs::File::create(full_path)
                         .expect(&format!("Unable to create {}", short_path))
                         .write_all(&result.data)