diff --git a/gfx/wr/wrench/src/rawtest.rs b/gfx/wr/wrench/src/rawtest.rs index 86bfb689d3db..d8fccb943083 100644 --- a/gfx/wr/wrench/src/rawtest.rs +++ b/gfx/wr/wrench/src/rawtest.rs @@ -40,6 +40,7 @@ impl<'a> RawtestHarness<'a> { self.test_tile_decomposition(); self.test_very_large_blob(); self.test_blob_visible_area(); + self.test_blob_set_visible_area(); self.test_offscreen_blob(); self.test_save_restore(); self.test_blur_cache(); @@ -464,6 +465,173 @@ impl<'a> RawtestHarness<'a> { *self.wrench.callbacks.lock().unwrap() = blob::BlobCallbacks::new(); } + fn test_blob_set_visible_area(&mut self) { + // In this test we first render a blob with a certain visible area, + // then change the visible area without updating the blob image. + + println!("\tblob visible area update..."); + + assert_eq!(self.wrench.device_pixel_ratio, 1.0); + + let window_size = self.window.get_inner_size(); + let test_size = FramebufferIntSize::new(800, 800); + let window_rect = FramebufferIntRect::new( + FramebufferIntPoint::new(0, window_size.height - test_size.height), + test_size, + ); + let layout_size = LayoutSize::new(800.0, 800.0); + let mut txn = Transaction::new(); + + let blob_img = self.wrench.api.generate_blob_image_key(); + txn.add_blob_image( + blob_img, + ImageDescriptor::new(500, 500, ImageFormat::BGRA8, false, false), + blob::serialize_blob(ColorU::new(50, 50, 150, 255)), + DeviceIntRect { + origin: point2(0, 0), + size: size2(500, 500), + }, + Some(128), + ); + + let mut builder = DisplayListBuilder::new(self.wrench.root_pipeline_id, layout_size); + + let root_space_and_clip = SpaceAndClipInfo::root_scroll(self.wrench.root_pipeline_id); + let clip_id = builder.define_clip( + &root_space_and_clip, + rect(-1000.0, -1000.0, 2000.0, 2000.0), + vec![], + None, + ); + + let info = CommonItemProperties { + clip_rect: rect(0.0, 0.0, 1000.0, 1000.0), + clip_id, + spatial_id: root_space_and_clip.spatial_id, + flags: PrimitiveFlags::default(), + hit_info: None, + }; + + builder.push_repeating_image( + &info, + rect(0.0, 0.0, 500.0, 500.0), + size2(500.0, 500.0), + size2(500.0, 500.0), + ImageRendering::Auto, + AlphaType::PremultipliedAlpha, + blob_img.as_image(), + ColorF::WHITE, + ); + let mut epoch = Epoch(0); + + // Render the first display list. We don't care about the result but we + // want to make sure the next display list updates an already rendered + // state. + self.submit_dl(&mut epoch, layout_size, builder, &txn.resource_updates); + let _ = self.render_and_get_pixels(window_rect); + + // Now render a similar scene with an updated blob visible area. + // In this test we care about the fact that the visible area was updated + // without using update_blob_image. + + let mut txn = Transaction::new(); + + txn.set_blob_image_visible_area(blob_img, DeviceIntRect { + origin: point2(50, 50), + size: size2(400, 400), + }); + + let mut builder = DisplayListBuilder::new(self.wrench.root_pipeline_id, layout_size); + + let root_space_and_clip = SpaceAndClipInfo::root_scroll(self.wrench.root_pipeline_id); + let clip_id = builder.define_clip( + &root_space_and_clip, + rect(-1000.0, -1000.0, 2000.0, 2000.0), + vec![], + None, + ); + + let info = CommonItemProperties { + clip_rect: rect(0.0, 0.0, 1000.0, 1000.0), + clip_id, + spatial_id: root_space_and_clip.spatial_id, + flags: PrimitiveFlags::default(), + hit_info: None, + }; + + builder.push_repeating_image( + &info, + rect(50.0, 50.0, 400.0, 400.0), + size2(400.0, 400.0), + size2(400.0, 400.0), + ImageRendering::Auto, + AlphaType::PremultipliedAlpha, + blob_img.as_image(), + ColorF::WHITE, + ); + + self.submit_dl(&mut epoch, layout_size, builder, &txn.resource_updates); + let resized_pixels = self.render_and_get_pixels(window_rect); + + // Now render the same scene with a new blob image created with the same + // visible area as the previous scene, without going through an update. + + let mut txn = Transaction::new(); + + let blob_img2 = self.wrench.api.generate_blob_image_key(); + txn.add_blob_image( + blob_img2, + ImageDescriptor::new(500, 500, ImageFormat::BGRA8, false, false), + blob::serialize_blob(ColorU::new(50, 50, 150, 255)), + DeviceIntRect { + origin: point2(50, 50), + size: size2(400, 400), + }, + Some(128), + ); + + let mut builder = DisplayListBuilder::new(self.wrench.root_pipeline_id, layout_size); + + let root_space_and_clip = SpaceAndClipInfo::root_scroll(self.wrench.root_pipeline_id); + let clip_id = builder.define_clip( + &root_space_and_clip, + rect(-1000.0, -1000.0, 2000.0, 2000.0), + vec![], + None, + ); + + let info = CommonItemProperties { + clip_rect: rect(0.0, 0.0, 1000.0, 1000.0), + clip_id, + spatial_id: root_space_and_clip.spatial_id, + flags: PrimitiveFlags::default(), + hit_info: None, + }; + + builder.push_repeating_image( + &info, + rect(50.0, 50.0, 400.0, 400.0), + size2(400.0, 400.0), + size2(400.0, 400.0), + ImageRendering::Auto, + AlphaType::PremultipliedAlpha, + blob_img2.as_image(), + ColorF::WHITE, + ); + let mut epoch = Epoch(0); + + self.submit_dl(&mut epoch, layout_size, builder, &txn.resource_updates); + + let reference_pixels = self.render_and_get_pixels(window_rect); + + assert_eq!(resized_pixels, reference_pixels); + + txn = Transaction::new(); + txn.delete_blob_image(blob_img); + txn.delete_blob_image(blob_img2); + self.wrench.api.update_resources(txn.resource_updates); + } + fn test_offscreen_blob(&mut self) { println!("\toffscreen blob update...");