From d8f0040134599a28ecfafc50487e731b50916c47 Mon Sep 17 00:00:00 2001 From: Martin Robinson Date: Thu, 22 Jun 2017 15:53:02 +0200 Subject: [PATCH 1/4] Add a define_scroll_frame API This makes it explicit whether or not you are creating a ScrollFrame when using the API. Before this was based on the content size of the clip, which was awkward and could lead to weird situations where you created a ScrollFrame when you didn't mean to or the reverse. Fixes #1335. --- webrender/examples/basic.rs | 5 +- webrender/examples/nested_display_list.rs | 20 ++-- webrender/examples/scrolling.rs | 16 +-- webrender/src/frame.rs | 69 +++++++++---- webrender_api/src/display_item.rs | 4 +- webrender_api/src/display_list.rs | 97 ++++++++++--------- wrench/reftests/mask/aligned-layer-rect.yaml | 4 +- .../mask/mask-transformed-to-empty-rect.yaml | 2 +- wrench/reftests/mask/nested-mask.yaml | 4 +- wrench/reftests/mask/out-of-bounds.yaml | 2 +- wrench/reftests/mask/rounded-corners.yaml | 2 +- wrench/reftests/scrolling/empty-mask.yaml | 2 +- .../fixed-position-scrolling-clip.yaml | 2 +- .../scrolling/nested-scroll-offset.yaml | 6 +- .../scrolling/out-of-bounds-scroll.yaml | 2 +- .../scrolling/scroll-layer-with-mask.yaml | 6 +- wrench/reftests/scrolling/scroll-layer.yaml | 2 +- wrench/reftests/scrolling/simple.yaml | 4 +- .../reftests/scrolling/translate-nested.yaml | 2 +- wrench/src/yaml_frame_reader.rs | 33 +++++-- wrench/src/yaml_frame_writer.rs | 44 ++++++--- 21 files changed, 202 insertions(+), 126 deletions(-) diff --git a/webrender/examples/basic.rs b/webrender/examples/basic.rs index 8e0acdb1ef..45f4a05cd1 100644 --- a/webrender/examples/basic.rs +++ b/webrender/examples/basic.rs @@ -197,7 +197,8 @@ fn body(api: &RenderApi, repeat: false, }; let complex = ComplexClipRegion::new((50, 50).to(150, 150), BorderRadius::uniform(20.0)); - builder.push_clip_node(None, bounds, bounds, vec![complex], Some(mask)); + let id = builder.define_clip(None, bounds, vec![complex], Some(mask)); + builder.push_clip_id(id); let bounds = (100, 100).to(200, 200); builder.push_rect(bounds, bounds, ColorF::new(0.0, 1.0, 0.0, 1.0)); @@ -319,7 +320,7 @@ fn body(api: &RenderApi, box_shadow_type); } - builder.pop_clip_node(); + builder.pop_clip_id(); builder.pop_stacking_context(); } diff --git a/webrender/examples/nested_display_list.rs b/webrender/examples/nested_display_list.rs index 53661917a5..4998c5d72d 100644 --- a/webrender/examples/nested_display_list.rs +++ b/webrender/examples/nested_display_list.rs @@ -34,11 +34,11 @@ fn body(_api: &RenderApi, outer_scroll_frame_rect, ColorF::new(1.0, 1.0, 1.0, 1.0)); - let nested_clip_id = builder.define_clip(None, - (100, 100).to(1000, 1000), - outer_scroll_frame_rect, - vec![], - None); + let nested_clip_id = builder.define_scroll_frame(None, + (100, 100).to(1000, 1000), + outer_scroll_frame_rect, + vec![], + None); builder.push_clip_id(nested_clip_id); let mut builder2 = DisplayListBuilder::new(*pipeline_id, *layout_size); @@ -67,11 +67,11 @@ fn body(_api: &RenderApi, builder3.push_rect(inner_scroll_frame_rect, inner_scroll_frame_rect, ColorF::new(1.0, 0.0, 1.0, 0.5)); - let inner_nested_clip_id = builder3.define_clip(None, - (330, 110).to(2000, 2000), - inner_scroll_frame_rect, - vec![], - None); + let inner_nested_clip_id = builder3.define_scroll_frame(None, + (330, 110).to(2000, 2000), + inner_scroll_frame_rect, + vec![], + None); builder3.push_clip_id(inner_nested_clip_id); let rect = (340, 120).to(440, 220); builder3.push_rect(rect, rect, ColorF::new(0.0, 1.0, 0.0, 1.0)); diff --git a/webrender/examples/scrolling.rs b/webrender/examples/scrolling.rs index a843a736d7..d83b8ab687 100644 --- a/webrender/examples/scrolling.rs +++ b/webrender/examples/scrolling.rs @@ -41,7 +41,11 @@ fn body(_api: &RenderApi, MixBlendMode::Normal, Vec::new()); // set the scrolling clip - let clip_id = builder.define_clip(None, (0, 0).by(1000, 1000), scrollbox, vec![], None); + let clip_id = builder.define_scroll_frame(None, + (0, 0).by(1000, 1000), + scrollbox, + vec![], + None); builder.push_clip_id(clip_id); // now put some content into it. @@ -62,11 +66,11 @@ fn body(_api: &RenderApi, // Below the above rectangles, set up a nested scrollbox. It's still in // the same stacking context, so note that the rects passed in need to // be relative to the stacking context. - let nested_clip_id = builder.define_clip(None, - (0, 100).to(300, 400), - (0, 100).to(200, 300), - vec![], - None); + let nested_clip_id = builder.define_scroll_frame(None, + (0, 100).to(300, 400), + (0, 100).to(200, 300), + vec![], + None); builder.push_clip_id(nested_clip_id); // give it a giant gray background just to distinguish it and to easily diff --git a/webrender/src/frame.rs b/webrender/src/frame.rs index a31283a612..4752ac0dc8 100644 --- a/webrender/src/frame.rs +++ b/webrender/src/frame.rs @@ -345,32 +345,46 @@ impl Frame { item: &ClipDisplayItem, content_rect: &LayerRect, clip: &ClipRegion) { - let is_scroll_frame = - clip.main.origin != LayerPoint::zero() || clip.main.size != content_rect.size; - let new_id = context.convert_new_id_to_neested(&item.id); - let new_clip_id = if is_scroll_frame { - self.clip_scroll_tree.generate_new_clip_id(pipeline_id) - } else { - new_id - }; - let clip_viewport = LayerRect::new(content_rect.origin, clip.main.size); - context.builder.add_clip_scroll_node(new_clip_id, + + let mut clip = *clip; + clip.main.origin = LayerPoint::zero(); + + context.builder.add_clip_scroll_node(new_id, parent_id, pipeline_id, &clip_viewport, - clip, + &clip, &mut self.clip_scroll_tree); - if is_scroll_frame { - context.builder.add_scroll_frame(new_id, - new_clip_id, + } + + fn flatten_scroll_frame<'a>(&mut self, + context: &mut FlattenContext, + pipeline_id: PipelineId, + parent_id: ClipId, + item: &ClipDisplayItem, + content_rect: &LayerRect, + clip: &ClipRegion) { + let clip_viewport = LayerRect::new(content_rect.origin, clip.main.size); + let clip_id = self.clip_scroll_tree.generate_new_clip_id(pipeline_id); + + let mut clip = *clip; + clip.main.origin = LayerPoint::zero(); + context.builder.add_clip_scroll_node(clip_id, + parent_id, pipeline_id, - &content_rect, &clip_viewport, + &clip, &mut self.clip_scroll_tree); - } + let new_id = context.convert_new_id_to_neested(&item.id); + context.builder.add_scroll_frame(new_id, + clip_id, + pipeline_id, + &content_rect, + &clip_viewport, + &mut self.clip_scroll_tree); } fn flatten_stacking_context<'a>(&mut self, @@ -656,12 +670,33 @@ impl Frame { } SpecificDisplayItem::Clip(ref info) => { let content_rect = &item.rect().translate(&reference_frame_relative_offset); + + let mut clip_region = ClipRegion::new(item.clip_rect(), info.image_mask); + let &(complex_clips, complex_clip_count) = item.complex_clip(); + clip_region.complex_clip_count = complex_clip_count; + clip_region.complex_clips = complex_clips; + self.flatten_clip(context, pipeline_id, clip_and_scroll.scroll_node_id, &info, &content_rect, - item.clip_region()); + &clip_region); + } + SpecificDisplayItem::ScrollFrame(ref info) => { + let content_rect = &item.rect().translate(&reference_frame_relative_offset); + + let mut clip_region = ClipRegion::new(item.clip_rect(), info.image_mask); + let &(complex_clips, complex_clip_count) = item.complex_clip(); + clip_region.complex_clip_count = complex_clip_count; + clip_region.complex_clips = complex_clips; + + self.flatten_scroll_frame(context, + pipeline_id, + clip_and_scroll.scroll_node_id, + &info, + &content_rect, + &clip_region); } SpecificDisplayItem::PushNestedDisplayList => { // Using the clip and scroll already processed for nesting here diff --git a/webrender_api/src/display_item.rs b/webrender_api/src/display_item.rs index d1c8099457..503bf5e062 100644 --- a/webrender_api/src/display_item.rs +++ b/webrender_api/src/display_item.rs @@ -50,6 +50,7 @@ pub struct DisplayItem { #[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)] pub enum SpecificDisplayItem { Clip(ClipDisplayItem), + ScrollFrame(ClipDisplayItem), Rectangle(RectangleDisplayItem), Text(TextDisplayItem), Image(ImageDisplayItem), @@ -71,7 +72,8 @@ pub enum SpecificDisplayItem { pub struct ClipDisplayItem { pub id: ClipId, pub parent_id: ClipId, - pub clip_region: ClipRegion, + pub content_rect: LayoutRect, + pub image_mask: Option, } #[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)] diff --git a/webrender_api/src/display_list.rs b/webrender_api/src/display_list.rs index e597d89658..aeb5fef041 100644 --- a/webrender_api/src/display_list.rs +++ b/webrender_api/src/display_list.rs @@ -7,12 +7,12 @@ use bincode; use serde::{Deserialize, Serialize, Serializer}; use serde::ser::{SerializeSeq, SerializeMap}; use time::precise_time_ns; -use {ImageMask, BorderDetails, BorderDisplayItem, BorderWidths, BoxShadowClipMode, BoxShadowDisplayItem}; -use {ClipAndScrollInfo, ClipDisplayItem, ClipId, ClipRegion, ColorF, ComplexClipRegion}; -use {DisplayItem, ExtendMode, FilterOp, FontKey, GlyphInstance, GlyphOptions, Gradient}; -use {GradientDisplayItem, GradientStop, IframeDisplayItem, ImageDisplayItem, ImageKey}; -use {ImageRendering, LayoutPoint, LayoutRect, LayoutSize, LayoutTransform, LayoutVector2D}; -use {MixBlendMode, PipelineId, PropertyBinding, PushStackingContextDisplayItem, RadialGradient}; +use {BorderDetails, BorderDisplayItem, BorderWidths, BoxShadowClipMode, BoxShadowDisplayItem}; +use {ClipAndScrollInfo, ClipDisplayItem, ClipId, ColorF, ComplexClipRegion, DisplayItem}; +use {ExtendMode, FilterOp, FontKey, GlyphInstance, GlyphOptions, Gradient, GradientDisplayItem}; +use {GradientStop, IframeDisplayItem, ImageDisplayItem, ImageKey, ImageMask, ImageRendering}; +use {LayoutPoint, LayoutRect, LayoutSize, LayoutTransform, LayoutVector2D, MixBlendMode}; +use {PipelineId, PropertyBinding, PushStackingContextDisplayItem, RadialGradient}; use {RadialGradientDisplayItem, RectangleDisplayItem, ScrollPolicy, SpecificDisplayItem}; use {StackingContext, TextDisplayItem, TransformStyle, WebGLContextId, WebGLDisplayItem}; use {YuvColorSpace, YuvData, YuvImageDisplayItem}; @@ -67,7 +67,7 @@ pub struct BuiltDisplayListIter<'a> { cur_stops: ItemRange, cur_glyphs: ItemRange, cur_filters: ItemRange, - cur_clip: ClipRegion, + cur_complex_clip: (ItemRange, usize), peeking: Peek, } @@ -143,7 +143,7 @@ impl<'a> BuiltDisplayListIter<'a> { cur_stops: ItemRange::default(), cur_glyphs: ItemRange::default(), cur_filters: ItemRange::default(), - cur_clip: ClipRegion::empty(), + cur_complex_clip: (ItemRange::default(), 0), peeking: Peek::NotPeeking, } } @@ -168,7 +168,7 @@ impl<'a> BuiltDisplayListIter<'a> { // Don't let these bleed into another item self.cur_stops = ItemRange::default(); - self.cur_clip = ClipRegion::empty(); + self.cur_complex_clip = (ItemRange::default(), 0); loop { if self.data.len() == 0 { @@ -185,12 +185,8 @@ impl<'a> BuiltDisplayListIter<'a> { // This is a dummy item, skip over it continue; } - Clip(clip) => { - self.cur_clip = clip.clip_region; - let (clip_range, clip_count) = self.skip_slice::(); - self.cur_clip.complex_clip_count = clip_count; - self.cur_clip.complex_clips = clip_range; - } + Clip(_) | ScrollFrame(_) => + self.cur_complex_clip = self.skip_slice::(), Text(_) => self.cur_glyphs = self.skip_slice::().0, PushStackingContext(_) => self.cur_filters = self.skip_slice::().0, _ => { /* do nothing */ } @@ -288,8 +284,8 @@ impl<'a, 'b> DisplayItemRef<'a, 'b> { &self.iter.cur_item.item } - pub fn clip_region(&self) -> &ClipRegion { - &self.iter.cur_clip + pub fn complex_clip(&self) -> &(ItemRange, usize) { + &self.iter.cur_complex_clip } pub fn gradient_stops(&self) -> ItemRange { @@ -383,13 +379,12 @@ impl<'a, 'b> Serialize for DisplayItemRef<'a, 'b> { _ => { } } - let clip_region = self.clip_region(); + let &(complex_clips, number_of_complex_clips) = self.complex_clip(); let gradient_stops = self.gradient_stops(); - map.serialize_entry("clip_region", &clip_region)?; - if !clip_region.complex_clips.is_empty() { + if number_of_complex_clips > 0 { map.serialize_entry("complex_clips", - &self.iter.list.get(clip_region.complex_clips).collect::>())?; + &self.iter.list.get(complex_clips).collect::>())?; } if !gradient_stops.is_empty() { @@ -837,46 +832,56 @@ impl DisplayListBuilder { self.push_iter(stops); } + fn generate_clip_id(&mut self, id: Option) -> ClipId { + id.unwrap_or_else(|| { + self.next_clip_id += 1; + ClipId::Clip(self.next_clip_id - 1, 0, self.pipeline_id) + }) + } + + pub fn define_scroll_frame(&mut self, + id: Option, + content_rect: LayoutRect, + clip_rect: LayoutRect, + complex_clips: I, + image_mask: Option) + -> ClipId + where I: IntoIterator, + I::IntoIter: ExactSizeIterator { + let id = self.generate_clip_id(id); + let item = SpecificDisplayItem::ScrollFrame(ClipDisplayItem { + id: id, + parent_id: self.clip_stack.last().unwrap().scroll_node_id, + image_mask: image_mask, + content_rect: content_rect, + }); + + self.push_item(item, content_rect, clip_rect); + self.push_iter(complex_clips); + id + } + pub fn define_clip(&mut self, id: Option, - content_rect: LayoutRect, clip_rect: LayoutRect, complex_clips: I, image_mask: Option) -> ClipId where I: IntoIterator, I::IntoIter: ExactSizeIterator { - let id = match id { - Some(id) => id, - None => { - self.next_clip_id += 1; - ClipId::Clip(self.next_clip_id - 1, 0, self.pipeline_id) - } - }; - + let id = self.generate_clip_id(id); let item = SpecificDisplayItem::Clip(ClipDisplayItem { id, parent_id: self.clip_stack.last().unwrap().scroll_node_id, - clip_region: ClipRegion::new(&clip_rect, image_mask), + image_mask: image_mask, + content_rect: clip_rect, }); - self.push_item(item, content_rect, clip_rect); + self.push_item(item, clip_rect, clip_rect); self.push_iter(complex_clips); id } - pub fn push_clip_node(&mut self, - id: Option, - content_rect: LayoutRect, - clip_rect: LayoutRect, - complex_clips: I, - image_mask: Option) - where I: IntoIterator, - I::IntoIter: ExactSizeIterator { - let id = self.define_clip(id, content_rect, clip_rect, complex_clips, image_mask); - self.clip_stack.push(ClipAndScrollInfo::simple(id)); - } - pub fn push_clip_id(&mut self, id: ClipId) { self.clip_stack.push(ClipAndScrollInfo::simple(id)); } @@ -890,10 +895,6 @@ impl DisplayListBuilder { assert!(self.clip_stack.len() > 0); } - pub fn pop_clip_node(&mut self) { - self.pop_clip_id(); - } - pub fn push_iframe(&mut self, rect: LayoutRect, pipeline_id: PipelineId) { let item = SpecificDisplayItem::Iframe(IframeDisplayItem { pipeline_id: pipeline_id }); self.push_item(item, rect, rect); diff --git a/wrench/reftests/mask/aligned-layer-rect.yaml b/wrench/reftests/mask/aligned-layer-rect.yaml index 5f52e3926c..a1c6e2f17e 100644 --- a/wrench/reftests/mask/aligned-layer-rect.yaml +++ b/wrench/reftests/mask/aligned-layer-rect.yaml @@ -1,11 +1,11 @@ --- root: items: - - type: scroll-layer + - type: scroll-frame bounds: [9, 9, 10, 10] content-size: [95, 88] items: - - type: scroll-layer + - type: scroll-frame bounds: [0, 0, 100, 100] items: - type: rect diff --git a/wrench/reftests/mask/mask-transformed-to-empty-rect.yaml b/wrench/reftests/mask/mask-transformed-to-empty-rect.yaml index 75afaabbe7..15ae96127a 100644 --- a/wrench/reftests/mask/mask-transformed-to-empty-rect.yaml +++ b/wrench/reftests/mask/mask-transformed-to-empty-rect.yaml @@ -7,7 +7,7 @@ root: z-index: 4 transform: [1, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, 0, 0, 150, -150, 1] items: - - type: scroll-layer + - type: clip bounds: [0, 0, 300, 300] # This image mask here assures that we will be forced to try to # mask instead of skipping it due to the mask rect becoming a diff --git a/wrench/reftests/mask/nested-mask.yaml b/wrench/reftests/mask/nested-mask.yaml index e6ebea3300..cacbb63434 100644 --- a/wrench/reftests/mask/nested-mask.yaml +++ b/wrench/reftests/mask/nested-mask.yaml @@ -1,14 +1,14 @@ --- root: items: - - type: scroll-layer + - type: clip bounds: [0, 0, 95, 88] image-mask: image: "mask.png" rect: [0, 0, 35, 35] repeat: false items: - - type: scroll-layer + - type: clip bounds: [0, 0, 95, 88] image-mask: image: "mask.png" diff --git a/wrench/reftests/mask/out-of-bounds.yaml b/wrench/reftests/mask/out-of-bounds.yaml index 6b1cb07e60..8e0eed09e0 100644 --- a/wrench/reftests/mask/out-of-bounds.yaml +++ b/wrench/reftests/mask/out-of-bounds.yaml @@ -1,7 +1,7 @@ --- root: items: - - type: scroll-layer + - type: clip bounds: [0, 0, 10000, 10000] complex: - rect: [0, 0, 10000, 10000] diff --git a/wrench/reftests/mask/rounded-corners.yaml b/wrench/reftests/mask/rounded-corners.yaml index ecb36e043f..e26a656cc0 100644 --- a/wrench/reftests/mask/rounded-corners.yaml +++ b/wrench/reftests/mask/rounded-corners.yaml @@ -1,7 +1,7 @@ --- root: items: - - type: scroll-layer + - type: clip bounds: [0, 0, 100, 100] complex: - rect: [0, 0, 100, 100] diff --git a/wrench/reftests/scrolling/empty-mask.yaml b/wrench/reftests/scrolling/empty-mask.yaml index 634c125559..69378dd5ad 100644 --- a/wrench/reftests/scrolling/empty-mask.yaml +++ b/wrench/reftests/scrolling/empty-mask.yaml @@ -3,7 +3,7 @@ root: - type: rect bounds: [0, 0, 100, 100] color: green - - type: scroll-layer + - type: scroll-frame bounds: [0, 0, 100, 100] items: - type: clip diff --git a/wrench/reftests/scrolling/fixed-position-scrolling-clip.yaml b/wrench/reftests/scrolling/fixed-position-scrolling-clip.yaml index d2285d56aa..270b227157 100644 --- a/wrench/reftests/scrolling/fixed-position-scrolling-clip.yaml +++ b/wrench/reftests/scrolling/fixed-position-scrolling-clip.yaml @@ -1,6 +1,6 @@ root: items: - - type: scroll-layer + - type: scroll-frame bounds: [10, 10, 100, 300] content-size: [100, 700] id: 41 diff --git a/wrench/reftests/scrolling/nested-scroll-offset.yaml b/wrench/reftests/scrolling/nested-scroll-offset.yaml index c16aaba073..850468f180 100644 --- a/wrench/reftests/scrolling/nested-scroll-offset.yaml +++ b/wrench/reftests/scrolling/nested-scroll-offset.yaml @@ -1,14 +1,14 @@ root: items: - - type: scroll-layer + - type: scroll-frame bounds: [0, 0, 500, 500] content-size: [1000, 1000] scroll-offset: [0, 300] items: - - type: scroll-layer + - type: scroll-frame bounds: [0, 300, 50, 50] items: - - type: scroll-layer + - type: scroll-frame bounds: [0, 300, 50, 50] items: - type: rect diff --git a/wrench/reftests/scrolling/out-of-bounds-scroll.yaml b/wrench/reftests/scrolling/out-of-bounds-scroll.yaml index 61d63d6f49..8c87bd6f5c 100644 --- a/wrench/reftests/scrolling/out-of-bounds-scroll.yaml +++ b/wrench/reftests/scrolling/out-of-bounds-scroll.yaml @@ -1,6 +1,6 @@ root: items: - - type: scroll-layer + - type: scroll-frame bounds: [10, 10, 50, 100] content-size: [50, 200] scroll-offset: [0, 50] diff --git a/wrench/reftests/scrolling/scroll-layer-with-mask.yaml b/wrench/reftests/scrolling/scroll-layer-with-mask.yaml index 841beef510..66b661df31 100644 --- a/wrench/reftests/scrolling/scroll-layer-with-mask.yaml +++ b/wrench/reftests/scrolling/scroll-layer-with-mask.yaml @@ -8,7 +8,7 @@ root: bounds: [10, 10, 100, 100] scroll-policy: scrollable items: - - type: scroll-layer + - type: scroll-frame bounds: [0, 0, 100, 100] image-mask: image: "mask.png" @@ -25,7 +25,7 @@ root: bounds: [100, 0, 100, 100] scroll-policy: scrollable items: - - type: scroll-layer + - type: scroll-frame bounds: [10, 10, 100, 300] scroll-offset: [0, 100] image-mask: @@ -40,7 +40,7 @@ root: # Same as the previous case, but this time we verify that a scroll layer that is # not at the origin works as well. - - type: scroll-layer + type: scroll-frame bounds: [210, 10, 100, 100] content-size: [100, 300] scroll-offset: [0, 100] diff --git a/wrench/reftests/scrolling/scroll-layer.yaml b/wrench/reftests/scrolling/scroll-layer.yaml index fa108573e0..4956672a77 100644 --- a/wrench/reftests/scrolling/scroll-layer.yaml +++ b/wrench/reftests/scrolling/scroll-layer.yaml @@ -1,6 +1,6 @@ root: items: - - type: scroll-layer + - type: scroll-frame bounds: [0, 0, 100, 100] content-size: [1000, 1000] scroll-offset: [50, 50] diff --git a/wrench/reftests/scrolling/simple.yaml b/wrench/reftests/scrolling/simple.yaml index efbc72f2d6..b8061dfca9 100644 --- a/wrench/reftests/scrolling/simple.yaml +++ b/wrench/reftests/scrolling/simple.yaml @@ -1,13 +1,13 @@ root: items: - - type: scroll-layer + - type: scroll-frame bounds: [10, 10, 50, 50] content-size: [100, 100] items: - type: rect bounds: [10, 10, 500, 500] color: green - - type: scroll-layer + - type: scroll-frame bounds: [70, 10, 50, 50] content-size: [100, 100] items: diff --git a/wrench/reftests/scrolling/translate-nested.yaml b/wrench/reftests/scrolling/translate-nested.yaml index 1f2cefd1b3..1607a01171 100644 --- a/wrench/reftests/scrolling/translate-nested.yaml +++ b/wrench/reftests/scrolling/translate-nested.yaml @@ -8,7 +8,7 @@ root: items: - bounds: [0, 0, 200, 200] - type: scroll-layer + type: clip id: 1 items: - diff --git a/wrench/src/yaml_frame_reader.rs b/wrench/src/yaml_frame_reader.rs index 1ad37b4eba..513b171be2 100644 --- a/wrench/src/yaml_frame_reader.rs +++ b/wrench/src/yaml_frame_reader.rs @@ -554,7 +554,7 @@ impl YamlFrameReader { "rect" => self.handle_rect(item, clip_rect), "image" => self.handle_image(wrench, item, clip_rect), "text" | "glyphs" => self.handle_text(wrench, item, clip_rect), - "scroll-layer" => self.handle_scroll_layer(wrench, item), + "scroll-frame" => self.handle_scroll_frame(wrench, item), "clip" => self.handle_clip(wrench, item), "border" => self.handle_border(wrench, item, clip_rect), "gradient" => self.handle_gradient(item, clip_rect), @@ -571,11 +571,7 @@ impl YamlFrameReader { } } - pub fn handle_scroll_layer(&mut self, wrench: &mut Wrench, yaml: &Yaml) { - self.handle_clip(wrench, yaml); - } - - pub fn handle_clip(&mut self, wrench: &mut Wrench, yaml: &Yaml) { + pub fn handle_scroll_frame(&mut self, wrench: &mut Wrench, yaml: &Yaml) { let bounds = yaml["bounds"].as_rect().expect("clip must have a bounds"); let content_size = yaml["content-size"].as_size().unwrap_or(bounds.size); let content_rect = LayerRect::new(bounds.origin, content_size); @@ -585,7 +581,30 @@ impl YamlFrameReader { let complex_clips = self.to_complex_clip_regions(&yaml["complex"]); let image_mask = self.to_image_mask(&yaml["image-mask"], wrench); - let id = self.builder().define_clip(id, content_rect, clip_rect, complex_clips, image_mask); + let id = self.builder().define_scroll_frame(id, + content_rect, + clip_rect, + complex_clips, + image_mask); + + if let Some(size) = yaml["scroll-offset"].as_point() { + self.scroll_offsets.insert(id, LayerPoint::new(size.x, size.y)); + } + + self.builder().push_clip_id(id); + if !yaml["items"].is_badvalue() { + self.add_display_list_items_from_yaml(wrench, &yaml["items"]); + } + self.builder().pop_clip_id(); + } + + pub fn handle_clip(&mut self, wrench: &mut Wrench, yaml: &Yaml) { + let clip_rect = yaml["bounds"].as_rect().expect("clip must have a bounds"); + let id = yaml["id"].as_i64().map(|id| ClipId::new(id as u64, self.builder().pipeline_id)); + let complex_clips = self.to_complex_clip_regions(&yaml["complex"]); + let image_mask = self.to_image_mask(&yaml["image-mask"], wrench); + + let id = self.builder().define_clip(id, clip_rect, complex_clips, image_mask); if let Some(size) = yaml["scroll-offset"].as_point() { self.scroll_offsets.insert(id, LayerPoint::new(size.x, size.y)); diff --git a/wrench/src/yaml_frame_writer.rs b/wrench/src/yaml_frame_writer.rs index 7b226d9be9..4c67dd1670 100644 --- a/wrench/src/yaml_frame_writer.rs +++ b/wrench/src/yaml_frame_writer.rs @@ -433,14 +433,15 @@ impl YamlFrameWriter { } fn make_clip_complex_node(&mut self, - clip: &ClipRegion, + complex_clip_count: usize, + complex_clips: ItemRange, list: &BuiltDisplayList) -> Option { - if clip.complex_clip_count == 0 { + if complex_clip_count == 0 { return None; } - let complex_items = list.get(clip.complex_clips).map(|ccx| + let complex_items = list.get(complex_clips).map(|ccx| if ccx.radii.is_zero() { rect_yaml(&ccx.rect) } else { @@ -453,10 +454,10 @@ impl YamlFrameWriter { Some(Yaml::Array(complex_items)) } - fn make_clip_mask_image_node(&mut self, clip: &ClipRegion) -> Option { - let mask = match clip.image_mask { - Some(ref mask) => mask, - None => return None, + fn make_clip_mask_image_node(&mut self, image_mask: &Option) -> Option { + let mask = match image_mask { + &Some(ref mask) => mask, + &None => return None, }; let mut mask_table = new_table(); @@ -746,22 +747,35 @@ impl YamlFrameWriter { Clip(item) => { str_node(&mut v, "type", "clip"); usize_node(&mut v, "id", clip_id_mapper.add_id(item.id)); + size_node(&mut v, "content-size", &item.content_rect.size); - let mut bounds = base.rect(); - let content_size = bounds.size; - let clip_region = base.clip_region(); - bounds.size = clip_region.main.size; + let &(complex_clips, complex_clip_count) = base.complex_clip(); + if let Some(complex) = self.make_clip_complex_node(complex_clip_count, + complex_clips, + display_list) { + yaml_node(&mut v, "complex", complex); + } - rect_node(&mut v, "bounds", &bounds); - size_node(&mut v, "content-size", &content_size); + if let Some(mask_yaml) = self.make_clip_mask_image_node(&item.image_mask) { + yaml_node(&mut v, "image-mask", mask_yaml); + } + } + ScrollFrame(item) => { + str_node(&mut v, "type", "scroll-frame"); + usize_node(&mut v, "id", clip_id_mapper.add_id(item.id)); + size_node(&mut v, "content-size", &item.content_rect.size); - if let Some(complex) = self.make_clip_complex_node(clip_region, display_list) { + let &(complex_clips, complex_clip_count) = base.complex_clip(); + if let Some(complex) = self.make_clip_complex_node(complex_clip_count, + complex_clips, + display_list) { yaml_node(&mut v, "complex", complex); } - if let Some(mask_yaml) = self.make_clip_mask_image_node(clip_region) { + if let Some(mask_yaml) = self.make_clip_mask_image_node(&item.image_mask) { yaml_node(&mut v, "image-mask", mask_yaml); } + } PushNestedDisplayList => clip_id_mapper.push_nested_display_list_ids(clip_and_scroll_info), From dfd76c528f7fd3cafd7e043ace369cb14fa22b65 Mon Sep 17 00:00:00 2001 From: Martin Robinson Date: Sat, 24 Jun 2017 11:51:11 +0200 Subject: [PATCH 2/4] Make clip coordinates relative to stacking context Clip coordinates previously used a weird coordinate space relative to the origin of the display item. This was different than every other coordinate specified in the display list, so we smooth over this wrinkle. To do this we need to copy out the complex clips from the auxiliary list and adjust them so that they are relative to the scroll clip node. Fixes #1090. Fixes #1408. --- webrender/src/clip_scroll_node.rs | 65 +++----- webrender/src/frame.rs | 146 +++++++++--------- webrender/src/frame_builder.rs | 52 +++---- webrender/src/mask_cache.rs | 46 +++++- webrender/src/prim_store.rs | 20 +-- webrender_api/src/display_item.rs | 52 +------ webrender_api/src/display_list.rs | 2 - wrench/reftests/aa/rounded-rects.yaml | 6 +- wrench/reftests/border/degenerate-curve.yaml | 18 +-- .../scrolling/scroll-layer-with-mask.yaml | 4 +- wrench/src/yaml_frame_reader.rs | 7 +- wrench/src/yaml_frame_writer.rs | 5 +- 12 files changed, 186 insertions(+), 237 deletions(-) diff --git a/webrender/src/clip_scroll_node.rs b/webrender/src/clip_scroll_node.rs index 578b9f0a28..6d2768ff90 100644 --- a/webrender/src/clip_scroll_node.rs +++ b/webrender/src/clip_scroll_node.rs @@ -2,15 +2,14 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +use api::{ClipId, DeviceIntRect, LayerPixel, LayerPoint, LayerRect, LayerSize}; +use api::{LayerToScrollTransform, LayerToWorldTransform, LayerVector2D, PipelineId}; +use api::{ScrollClamping, ScrollEventPhase, ScrollLocation, WorldPoint}; use geometry::ray_intersects_rect; -use mask_cache::{ClipSource, MaskCacheInfo}; +use mask_cache::{ClipRegion, ClipSource, MaskCacheInfo}; use spring::{DAMPING, STIFFNESS, Spring}; -use tiling::{DisplayListMap, PackedLayerIndex}; +use tiling::PackedLayerIndex; use util::{ComplexClipRegionHelpers, MatrixHelpers, TransformedRectKind}; -use api::{ClipId, ClipRegion, DeviceIntRect, LayerPixel, LayerPoint, LayerRect}; -use api::{LayerSize, LayerToScrollTransform, LayerToWorldTransform, PipelineId}; -use api::{ScrollClamping, ScrollEventPhase, ScrollLocation}; -use api::{WorldPoint, LayerVector2D}; #[cfg(target_os = "macos")] const CAN_OVERSCROLL: bool = true; @@ -39,19 +38,23 @@ pub struct ClipInfo { /// The biggest final transformed rectangle that is completely inside the /// clipping region for this node. pub screen_inner_rect: DeviceIntRect, + + /// A rectangle which defines the rough boundaries of this clip in reference + /// frame relative coordinates (with no scroll offsets). + pub clip_rect: LayerRect, } impl ClipInfo { - pub fn new(clip_region: &ClipRegion, - packed_layer_index: PackedLayerIndex) - -> ClipInfo { - let clip_sources = vec![ClipSource::Region(clip_region.clone())]; + pub fn new(clip_region: ClipRegion, packed_layer_index: PackedLayerIndex) -> ClipInfo { + let clip_rect = LayerRect::new(clip_region.origin, clip_region.main.size); + let clip_sources = vec![ClipSource::Region(clip_region)]; ClipInfo { mask_cache_info: MaskCacheInfo::new(&clip_sources), clip_sources, packed_layer_index, screen_bounding_rect: None, screen_inner_rect: DeviceIntRect::zero(), + clip_rect: clip_rect, } } } @@ -118,11 +121,11 @@ pub struct ClipScrollNode { impl ClipScrollNode { pub fn new_scroll_frame(pipeline_id: PipelineId, parent_id: ClipId, - content_rect: &LayerRect, - frame_rect: &LayerRect) + frame_rect: &LayerRect, + content_size: &LayerSize) -> ClipScrollNode { ClipScrollNode { - content_size: content_rect.size, + content_size: *content_size, local_viewport_rect: *frame_rect, local_clip_rect: *frame_rect, combined_local_viewport_rect: LayerRect::zero(), @@ -136,29 +139,11 @@ impl ClipScrollNode { } } - pub fn new(pipeline_id: PipelineId, - parent_id: ClipId, - content_rect: &LayerRect, - clip_rect: &LayerRect, - clip_info: ClipInfo) - -> ClipScrollNode { - // FIXME(mrobinson): We don't yet handle clipping rectangles that don't start at the origin - // of the node. - // Accumulate the local clips - //Note: `MaskCacheInfo::bounds` have that intersection as well, - // but we don't have it by hand - let local_viewport_rect = LayerRect::new(content_rect.origin, clip_rect.size); - let local_clip_rect = clip_info.clip_sources.iter().fold( - Some(*clip_rect), |intersection, source| match *source { - ClipSource::Complex(rect, _, _) => intersection.and_then(|r| r.intersection(&rect)), - ClipSource::Region(ref region) => intersection.and_then(|r| r.intersection(®ion.main)), - ClipSource::BorderCorner(_) => intersection, - } - ); + pub fn new(pipeline_id: PipelineId, parent_id: ClipId, clip_info: ClipInfo) -> ClipScrollNode { ClipScrollNode { - content_size: content_rect.size, - local_viewport_rect, - local_clip_rect: LayerRect::new(content_rect.origin, local_clip_rect.unwrap_or(LayerRect::zero()).size), + content_size: clip_info.clip_rect.size, + local_viewport_rect: clip_info.clip_rect, + local_clip_rect: clip_info.clip_rect, combined_local_viewport_rect: LayerRect::zero(), world_viewport_transform: LayerToWorldTransform::identity(), world_content_transform: LayerToWorldTransform::identity(), @@ -409,10 +394,7 @@ impl ClipScrollNode { } } - pub fn find_unclipped_rectangle(&self, - display_lists: &DisplayListMap, - rect: &LayerRect) - -> Option { + pub fn find_unclipped_rectangle(&self, rect: &LayerRect) -> Option { let clip_sources = match self.node_type { NodeType::Clip(ref clip_info) => &clip_info.clip_sources, _ => return None, @@ -428,11 +410,8 @@ impl ClipScrollNode { } let offset = &self.local_viewport_rect.origin.to_vector(); - let display_list = display_lists.get(&self.pipeline_id).expect("No display list?"); - let complex_clips = display_list.get(clip_region.complex_clips); - let base_rect = clip_region.main.translate(offset).intersection(rect); - complex_clips.fold(base_rect, |inner_combined, ccr| { + clip_region.complex_clips.iter().fold(base_rect, |inner_combined, ccr| { inner_combined.and_then(|combined| { ccr.get_inner_rect_full().and_then(|ir| { ir.translate(offset).intersection(&combined) diff --git a/webrender/src/frame.rs b/webrender/src/frame.rs index 4752ac0dc8..526020dfcf 100644 --- a/webrender/src/frame.rs +++ b/webrender/src/frame.rs @@ -2,7 +2,15 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +use api::{BuiltDisplayList, BuiltDisplayListIter, ClipAndScrollInfo, ClipId, ColorF}; +use api::{ComplexClipRegion, DeviceUintRect, DeviceUintSize, DisplayItemRef, Epoch}; +use api::{FilterOp, ImageDisplayItem, ItemRange, LayerPoint, LayerRect, LayerSize}; +use api::{LayerToScrollTransform, LayerVector2D, LayoutSize, LayoutTransform}; +use api::{MixBlendMode, PipelineId, ScrollClamping, ScrollEventPhase}; +use api::{ScrollLayerState, ScrollLocation, ScrollPolicy, SpecificDisplayItem}; +use api::{StackingContext, TileOffset, TransformStyle, WorldPoint}; use app_units::Au; +use clip_scroll_tree::{ClipScrollTree, ScrollStates}; use euclid::rect; use fnv::FnvHasher; use gpu_cache::GpuCache; @@ -10,7 +18,7 @@ use internal_types::{ANGLE_FLOAT_TO_FIXED, AxisDirection}; use internal_types::{LowLevelFilterOp}; use internal_types::{RendererFrame}; use frame_builder::{FrameBuilder, FrameBuilderConfig}; -use clip_scroll_tree::{ClipScrollTree, ScrollStates}; +use mask_cache::ClipRegion; use profiler::{GpuCacheProfileCounters, TextureCacheProfileCounters}; use resource_cache::ResourceCache; use scene::{Scene, SceneProperties}; @@ -19,13 +27,6 @@ use std::collections::HashMap; use std::hash::BuildHasherDefault; use tiling::{CompositeOps, DisplayListMap, PrimitiveFlags}; use util::subtract_rect; -use api::{BuiltDisplayList, BuiltDisplayListIter, ClipAndScrollInfo, ClipDisplayItem}; -use api::{ClipId, ClipRegion, ColorF, DeviceUintRect, DeviceUintSize, DisplayItemRef}; -use api::{Epoch, FilterOp, ImageDisplayItem, ItemRange, LayerPoint, LayerRect}; -use api::{LayerSize, LayerToScrollTransform, LayoutSize, LayoutTransform, LayerVector2D}; -use api::{MixBlendMode, PipelineId, ScrollClamping, ScrollEventPhase}; -use api::{ScrollLayerState, ScrollLocation, ScrollPolicy, SpecificDisplayItem}; -use api::{StackingContext, TileOffset, TransformStyle, WorldPoint}; #[derive(Copy, Clone, PartialEq, PartialOrd, Debug)] pub struct FrameId(pub u32); @@ -152,6 +153,20 @@ impl<'a> FlattenContext<'a> { _ => id, } } + + fn get_complex_clips(&self, + pipeline_id: PipelineId, + complex_clips: ItemRange) + -> Vec { + if complex_clips.is_empty() { + return vec![]; + } + + self.scene.display_lists.get(&pipeline_id) + .expect("No display list?") + .get(complex_clips) + .collect() + } } // TODO: doc @@ -341,49 +356,38 @@ impl Frame { fn flatten_clip<'a>(&mut self, context: &mut FlattenContext, pipeline_id: PipelineId, - parent_id: ClipId, - item: &ClipDisplayItem, - content_rect: &LayerRect, - clip: &ClipRegion) { - let new_id = context.convert_new_id_to_neested(&item.id); - let clip_viewport = LayerRect::new(content_rect.origin, clip.main.size); - - let mut clip = *clip; - clip.main.origin = LayerPoint::zero(); - - context.builder.add_clip_scroll_node(new_id, - parent_id, - pipeline_id, - &clip_viewport, - &clip, - &mut self.clip_scroll_tree); + parent_id: &ClipId, + new_clip_id: &ClipId, + clip_region: ClipRegion) { + let new_clip_id = context.convert_new_id_to_neested(new_clip_id); + context.builder.add_clip_node(new_clip_id, + *parent_id, + pipeline_id, + clip_region, + &mut self.clip_scroll_tree); } fn flatten_scroll_frame<'a>(&mut self, context: &mut FlattenContext, pipeline_id: PipelineId, - parent_id: ClipId, - item: &ClipDisplayItem, + parent_id: &ClipId, + new_scroll_frame_id: &ClipId, + frame_rect: &LayerRect, content_rect: &LayerRect, - clip: &ClipRegion) { - let clip_viewport = LayerRect::new(content_rect.origin, clip.main.size); + clip_region: ClipRegion) { let clip_id = self.clip_scroll_tree.generate_new_clip_id(pipeline_id); + context.builder.add_clip_node(clip_id, + *parent_id, + pipeline_id, + clip_region, + &mut self.clip_scroll_tree); - let mut clip = *clip; - clip.main.origin = LayerPoint::zero(); - context.builder.add_clip_scroll_node(clip_id, - parent_id, - pipeline_id, - &clip_viewport, - &clip, - &mut self.clip_scroll_tree); - - let new_id = context.convert_new_id_to_neested(&item.id); - context.builder.add_scroll_frame(new_id, + let new_scroll_frame_id = context.convert_new_id_to_neested(new_scroll_frame_id); + context.builder.add_scroll_frame(new_scroll_frame_id, clip_id, pipeline_id, - &content_rect, - &clip_viewport, + &frame_rect, + &content_rect.size, &mut self.clip_scroll_tree); } @@ -511,8 +515,8 @@ impl Frame { ClipId::root_scroll_node(pipeline_id), iframe_reference_frame_id, pipeline_id, - &LayerRect::new(LayerPoint::zero(), pipeline.content_size), &iframe_rect, + &pipeline.content_size, &mut self.clip_scroll_tree); self.flatten_root(&mut display_list.iter(), pipeline_id, context, &pipeline.content_size); @@ -592,8 +596,7 @@ impl Frame { item.clip_rect(), &info.color, &clip_and_scroll, - &reference_frame_relative_offset, - &context.scene.display_lists) { + &reference_frame_relative_offset) { context.builder.add_solid_rectangle(clip_and_scroll, &item.rect(), item.clip_rect(), @@ -669,34 +672,37 @@ impl Frame { reference_frame_relative_offset); } SpecificDisplayItem::Clip(ref info) => { - let content_rect = &item.rect().translate(&reference_frame_relative_offset); - - let mut clip_region = ClipRegion::new(item.clip_rect(), info.image_mask); - let &(complex_clips, complex_clip_count) = item.complex_clip(); - clip_region.complex_clip_count = complex_clip_count; - clip_region.complex_clips = complex_clips; + let complex_clips = context.get_complex_clips(pipeline_id, item.complex_clip().0); + let mut clip_region = ClipRegion::new(*item.clip_rect(), + info.image_mask, + complex_clips); + clip_region.origin += reference_frame_relative_offset; self.flatten_clip(context, pipeline_id, - clip_and_scroll.scroll_node_id, - &info, - &content_rect, - &clip_region); + &clip_and_scroll.scroll_node_id, + &info.id, + clip_region); } SpecificDisplayItem::ScrollFrame(ref info) => { - let content_rect = &item.rect().translate(&reference_frame_relative_offset); - - let mut clip_region = ClipRegion::new(item.clip_rect(), info.image_mask); - let &(complex_clips, complex_clip_count) = item.complex_clip(); - clip_region.complex_clip_count = complex_clip_count; - clip_region.complex_clips = complex_clips; - + let complex_clips = context.get_complex_clips(pipeline_id, item.complex_clip().0); + let mut clip_region = ClipRegion::new(*item.clip_rect(), + info.image_mask, + complex_clips); + clip_region.origin += reference_frame_relative_offset; + + // Just use clip rectangle as the frame rect for this scroll frame. + // This is only interesting when calculating scroll extents for the + // ClipScrollNode::scroll(..) API + let frame_rect = item.clip_rect().translate(&reference_frame_relative_offset); + let content_rect = item.rect().translate(&reference_frame_relative_offset); self.flatten_scroll_frame(context, pipeline_id, - clip_and_scroll.scroll_node_id, - &info, + &clip_and_scroll.scroll_node_id, + &info.id, + &frame_rect, &content_rect, - &clip_region); + clip_region); } SpecificDisplayItem::PushNestedDisplayList => { // Using the clip and scroll already processed for nesting here @@ -726,8 +732,7 @@ impl Frame { clip_rect: &LayerRect, color: &ColorF, clip_and_scroll: &ClipAndScrollInfo, - reference_frame_relative_offset: &LayerVector2D, - display_lists: &DisplayListMap) + reference_frame_relative_offset: &LayerVector2D) -> bool { // If this rectangle is not opaque, splitting the rectangle up // into an inner opaque region just ends up hurting batching and @@ -739,8 +744,7 @@ impl Frame { let (unclipped_rect, parent_clip_and_scroll) = match self.find_unclipped_rectangle(clip_and_scroll, rect, - reference_frame_relative_offset, - display_lists) { + reference_frame_relative_offset) { Some((rect, clip_and_scroll)) => (rect, clip_and_scroll), None => return false, }; @@ -771,8 +775,7 @@ impl Frame { fn find_unclipped_rectangle(&mut self, clip_and_scroll: &ClipAndScrollInfo, rect: &LayerRect, - reference_frame_relative_offset: &LayerVector2D, - display_lists: &DisplayListMap) + reference_frame_relative_offset: &LayerVector2D) -> Option<(LayerRect, ClipAndScrollInfo)> { // Try to extract the opaque inner rectangle out of the clipped primitive. if clip_and_scroll.scroll_node_id != clip_and_scroll.clip_node_id() { @@ -790,8 +793,7 @@ impl Frame { }; let rect_in_reference_frame = rect.translate(reference_frame_relative_offset); - let unclipped_rect = match clip_node.find_unclipped_rectangle(display_lists, - &rect_in_reference_frame) { + let unclipped_rect = match clip_node.find_unclipped_rectangle(&rect_in_reference_frame) { Some(rect) => rect, None => return None, }; diff --git a/webrender/src/frame_builder.rs b/webrender/src/frame_builder.rs index db3240efd9..10624f435f 100644 --- a/webrender/src/frame_builder.rs +++ b/webrender/src/frame_builder.rs @@ -2,11 +2,17 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +use api::{BorderDetails, BorderDisplayItem, BoxShadowClipMode, ClipAndScrollInfo, ClipId}; +use api::{ClipRegion, ColorF, DeviceIntPoint, DeviceIntRect, DeviceIntSize, DeviceUintRect}; +use api::{DeviceUintSize, ExtendMode, FontKey, FontRenderMode, GlyphInstance, GlyphOptions}; +use api::{GradientStop, ImageKey, ImageRendering, ItemRange, LayerPoint, LayerRect, LayerSize}; +use api::{LayerToScrollTransform, LayerVector2D, PipelineId, RepeatMode, TileOffset}; +use api::{TransformStyle, WebGLContextId, WorldPixel, YuvColorSpace, YuvData}; use app_units::Au; use frame::FrameId; use gpu_cache::GpuCache; use internal_types::HardwareCompositeOp; -use mask_cache::{ClipMode, ClipSource, MaskCacheInfo}; +use mask_cache::{ClipMode, ClipRegion, ClipSource, MaskCacheInfo}; use plane_split::{BspSplitter, Polygon, Splitter}; use prim_store::{GradientPrimitiveCpu, ImagePrimitiveCpu}; use prim_store::{ImagePrimitiveKind, PrimitiveContainer, PrimitiveIndex}; @@ -28,13 +34,6 @@ use tiling::{PackedLayer, PackedLayerIndex, PrimitiveFlags, PrimitiveRunCmd, Ren use tiling::{RenderTargetContext, RenderTaskCollection, ScrollbarPrimitive, StackingContext}; use util::{self, pack_as_float, subtract_rect, recycle_vec}; use util::{MatrixHelpers, RectHelpers}; -use api::{BorderDetails, BorderDisplayItem, BoxShadowClipMode, ClipAndScrollInfo}; -use api::{ClipId, ClipRegion, ColorF, DeviceIntPoint, DeviceIntRect, DeviceIntSize}; -use api::{DeviceUintRect, DeviceUintSize, ExtendMode, FontKey, FontRenderMode}; -use api::{GlyphInstance, GlyphOptions, GradientStop, ImageKey, ImageRendering}; -use api::{ItemRange, LayerPoint, LayerRect, LayerSize, LayerToScrollTransform}; -use api::{PipelineId, RepeatMode, TileOffset, TransformStyle, WebGLContextId}; -use api::{WorldPixel, YuvColorSpace, YuvData, LayerVector2D}; #[derive(Debug, Clone)] struct ImageBorderSegment { @@ -351,28 +350,21 @@ impl FrameBuilder { self.add_scroll_frame(topmost_scrolling_node_id, clip_scroll_tree.root_reference_frame_id, pipeline_id, - &LayerRect::new(LayerPoint::zero(), *content_size), &viewport_rect, + content_size, clip_scroll_tree); topmost_scrolling_node_id } - pub fn add_clip_scroll_node(&mut self, - new_node_id: ClipId, - parent_id: ClipId, - pipeline_id: PipelineId, - content_rect: &LayerRect, - clip_region: &ClipRegion, - clip_scroll_tree: &mut ClipScrollTree) { - let clip_info = ClipInfo::new(clip_region, - PackedLayerIndex(self.packed_layers.len())); - let node = ClipScrollNode::new(pipeline_id, - parent_id, - content_rect, - &clip_region.main, - clip_info); - + pub fn add_clip_node(&mut self, + new_node_id: ClipId, + parent_id: ClipId, + pipeline_id: PipelineId, + clip_region: ClipRegion, + clip_scroll_tree: &mut ClipScrollTree) { + let clip_info = ClipInfo::new(clip_region, PackedLayerIndex(self.packed_layers.len())); + let node = ClipScrollNode::new(pipeline_id, parent_id, clip_info); clip_scroll_tree.add_node(node, new_node_id); self.packed_layers.push(PackedLayer::empty()); } @@ -381,13 +373,13 @@ impl FrameBuilder { new_node_id: ClipId, parent_id: ClipId, pipeline_id: PipelineId, - content_rect: &LayerRect, frame_rect: &LayerRect, + content_size: &LayerSize, clip_scroll_tree: &mut ClipScrollTree) { let node = ClipScrollNode::new_scroll_frame(pipeline_id, parent_id, - content_rect, - frame_rect); + frame_rect, + content_size); clip_scroll_tree.add_node(node, new_node_id); } @@ -1574,14 +1566,10 @@ impl<'a> LayerRectCalculationAndCullingPass<'a> { }; node_clip_info.screen_inner_rect = inner_rect; - let display_list = self.display_lists.get(&node.pipeline_id) - .expect("No display list?"); - let bounds = node_clip_info.mask_cache_info.update(&node_clip_info.clip_sources, &transform, self.gpu_cache, - self.device_pixel_ratio, - display_list); + self.device_pixel_ratio); node_clip_info.screen_inner_rect = bounds.inner.as_ref() .and_then(|inner| inner.device_rect.intersection(&inner_rect)) diff --git a/webrender/src/mask_cache.rs b/webrender/src/mask_cache.rs index 5e205e6952..fb58352136 100644 --- a/webrender/src/mask_cache.rs +++ b/webrender/src/mask_cache.rs @@ -2,6 +2,8 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +use api::{BorderRadius, ComplexClipRegion, DeviceIntRect, ImageMask, LayerPoint}; +use api::{LayerRect, LayerSize, LayerToWorldTransform}; use border::BorderCornerClipSource; use gpu_cache::{GpuCache, GpuCacheHandle, ToGpuBlocks}; use prim_store::{CLIP_DATA_GPU_BLOCKS, ClipData, ImageMaskData}; @@ -13,6 +15,40 @@ use std::ops::Not; const MAX_CLIP: f32 = 1000000.0; +#[derive(Clone, Debug)] +pub struct ClipRegion { + pub origin: LayerPoint, + pub main: LayerRect, + pub image_mask: Option, + pub complex_clips: Vec, +} + +impl ClipRegion { + pub fn new(main: LayerRect, + mut image_mask: Option, + mut complex_clips: Vec) + -> ClipRegion { + let negative_origin = -main.origin.to_vector(); + + // All the coordinates we receive are relative to the stacking context, but we want + // to convert them to something relative to the origin of the clip. + if let Some(ref mut image_mask) = image_mask { + image_mask.rect = image_mask.rect.translate(&negative_origin); + } + + for ref mut complex_clip in complex_clips.iter_mut() { + complex_clip.rect = complex_clip.rect.translate(&negative_origin); + } + + ClipRegion { + origin: main.origin, + main: LayerRect::new(LayerPoint::zero(), main.size), + image_mask, + complex_clips, + } + } +} + #[repr(C)] #[derive(Copy, Clone, Debug, PartialEq)] pub enum ClipMode { @@ -158,7 +194,7 @@ impl MaskCacheInfo { debug_assert!(image.is_none()); // TODO(gw): Support >1 image mask! image = Some((info, GpuCacheHandle::new())); } - complex_clip_count += region.complex_clip_count; + complex_clip_count += region.complex_clips.len(); layer_clip_count += 1; } ClipSource::BorderCorner(ref source) => { @@ -183,8 +219,8 @@ impl MaskCacheInfo { sources: &[ClipSource], transform: &LayerToWorldTransform, gpu_cache: &mut GpuCache, - device_pixel_ratio: f32, - display_list: &BuiltDisplayList) -> &MaskBounds { + device_pixel_ratio: f32) + -> &MaskBounds { // Step[1] - compute the local bounds //TODO: move to initialization stage? @@ -220,7 +256,7 @@ impl MaskCacheInfo { None => local_rect, }; - for clip in display_list.get(region.complex_clips) { + for clip in ®ion.complex_clips { local_rect = local_rect.and_then(|r| r.intersection(&clip.rect)); local_inner = local_inner.and_then(|r| clip.get_inner_rect_safe() .and_then(|ref inner| r.intersection(inner))); @@ -264,7 +300,7 @@ impl MaskCacheInfo { data.write(&mut request); } ClipSource::Region(ref region) => { - for clip in display_list.get(region.complex_clips) { + for clip in ®ion.complex_clips { let data = ClipData::from_clip_region(&clip); data.write(&mut request); } diff --git a/webrender/src/prim_store.rs b/webrender/src/prim_store.rs index c4b6dfa226..64e2f764a8 100644 --- a/webrender/src/prim_store.rs +++ b/webrender/src/prim_store.rs @@ -2,23 +2,21 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +use api::{BuiltDisplayList, ColorF, ComplexClipRegion, DeviceIntRect, DeviceIntSize, DevicePoint}; +use api::{ExtendMode, FontKey, FontRenderMode, GlyphInstance, GlyphOptions, GradientStop}; +use api::{ImageKey, ImageRendering, ItemRange, LayerPoint, LayerRect, LayerSize}; +use api::{LayerToWorldTransform, TileOffset, WebGLContextId, YuvColorSpace, YuvFormat}; +use api::device_length; use app_units::Au; use border::BorderCornerInstance; use euclid::{Size2D}; use gpu_cache::{GpuCacheAddress, GpuBlockData, GpuCache, GpuCacheHandle, GpuDataRequest, ToGpuBlocks}; -use mask_cache::{ClipMode, ClipSource, MaskCacheInfo}; +use mask_cache::{ClipMode, ClipRegion, ClipSource, MaskCacheInfo}; use renderer::MAX_VERTEX_TEXTURE_WIDTH; use render_task::{RenderTask, RenderTaskLocation}; use resource_cache::{ImageProperties, ResourceCache}; use std::{mem, usize}; use util::{TransformedRect, recycle_vec}; -use api::{BuiltDisplayList, ColorF, ImageKey, ImageRendering, YuvColorSpace}; -use api::{YuvFormat, ClipRegion, ComplexClipRegion, ItemRange}; -use api::{FontKey, FontRenderMode, WebGLContextId}; -use api::{device_length, DeviceIntRect, DeviceIntSize}; -use api::{DevicePoint, LayerRect, LayerSize, LayerPoint}; -use api::{LayerToWorldTransform, GlyphInstance, GlyphOptions}; -use api::{ExtendMode, GradientStop, TileOffset}; pub const CLIP_DATA_GPU_BLOCKS: usize = 10; @@ -969,11 +967,7 @@ impl PrimitiveStore { let metadata = &mut self.cpu_metadata[prim_index.0]; if let Some(ref mut clip_info) = metadata.clip_cache_info { - clip_info.update(&metadata.clips, - layer_transform, - gpu_cache, - device_pixel_ratio, - display_list); + clip_info.update(&metadata.clips, layer_transform, gpu_cache, device_pixel_ratio); //TODO-LCCR: we could tighten up the `local_clip_rect` here // but that would require invalidating the whole GPU block diff --git a/webrender_api/src/display_item.rs b/webrender_api/src/display_item.rs index 503bf5e062..2e984d28d0 100644 --- a/webrender_api/src/display_item.rs +++ b/webrender_api/src/display_item.rs @@ -4,9 +4,8 @@ use app_units::Au; use euclid::SideOffsets2D; -use {ColorF, FontKey, ImageKey, ItemRange, PipelineId, WebGLContextId}; -use {LayoutPoint, LayoutRect, LayoutSize, LayoutTransform, LayoutVector2D}; -use {PropertyBinding}; +use {ColorF, FontKey, ImageKey, LayoutPoint, LayoutRect, LayoutSize, LayoutTransform}; +use {LayoutVector2D, PipelineId, PropertyBinding, WebGLContextId}; // NOTE: some of these structs have an "IMPLICIT" comment. // This indicates that the BuiltDisplayList will have serialized @@ -72,7 +71,6 @@ pub enum SpecificDisplayItem { pub struct ClipDisplayItem { pub id: ClipId, pub parent_id: ClipId, - pub content_rect: LayoutRect, pub image_mask: Option, } @@ -449,17 +447,6 @@ pub struct ImageMask { pub repeat: bool, } -#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)] -pub struct ClipRegion { - pub main: LayoutRect, - pub image_mask: Option, - #[serde(default, skip_serializing, skip_deserializing)] - pub complex_clips: ItemRange, - #[serde(default, skip_serializing, skip_deserializing)] - pub complex_clip_count: usize, -} - -#[repr(C)] #[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)] pub struct ComplexClipRegion { /// The boundaries of the rectangle. @@ -523,41 +510,6 @@ impl BorderRadius { } } -impl ClipRegion { - pub fn new(rect: &LayoutRect, - image_mask: Option) - -> ClipRegion { - ClipRegion { - main: *rect, - image_mask, - complex_clips: ItemRange::default(), - complex_clip_count: 0, - } - } - - pub fn simple(rect: &LayoutRect) -> ClipRegion { - ClipRegion { - main: *rect, - image_mask: None, - complex_clips: ItemRange::default(), - complex_clip_count: 0, - } - } - - pub fn empty() -> ClipRegion { - ClipRegion { - main: LayoutRect::zero(), - image_mask: None, - complex_clips: ItemRange::default(), - complex_clip_count: 0, - } - } - - pub fn is_complex(&self) -> bool { - self.complex_clip_count != 0 || self.image_mask.is_some() - } -} - impl ColorF { pub fn new(r: f32, g: f32, b: f32, a: f32) -> ColorF { ColorF { diff --git a/webrender_api/src/display_list.rs b/webrender_api/src/display_list.rs index aeb5fef041..8e6c90712d 100644 --- a/webrender_api/src/display_list.rs +++ b/webrender_api/src/display_list.rs @@ -853,7 +853,6 @@ impl DisplayListBuilder { id: id, parent_id: self.clip_stack.last().unwrap().scroll_node_id, image_mask: image_mask, - content_rect: content_rect, }); self.push_item(item, content_rect, clip_rect); @@ -874,7 +873,6 @@ impl DisplayListBuilder { id, parent_id: self.clip_stack.last().unwrap().scroll_node_id, image_mask: image_mask, - content_rect: clip_rect, }); self.push_item(item, clip_rect, clip_rect); diff --git a/wrench/reftests/aa/rounded-rects.yaml b/wrench/reftests/aa/rounded-rects.yaml index f103bd27a5..ab675ec8ee 100644 --- a/wrench/reftests/aa/rounded-rects.yaml +++ b/wrench/reftests/aa/rounded-rects.yaml @@ -8,7 +8,7 @@ root: - type: clip bounds: [50, 50, 200, 200] complex: - - rect: [0, 0, 200, 200] + - rect: [50, 50, 200, 200] radius: 8 items: - type: rect @@ -18,7 +18,7 @@ root: - type: clip bounds: [270, 50, 200, 200] complex: - - rect: [0, 0, 200, 200] + - rect: [270, 50, 200, 200] radius: [16, 32, 48, 64] items: - type: rect @@ -28,7 +28,7 @@ root: - type: clip bounds: [490, 50, 200, 200] complex: - - rect: [0, 0, 200, 200] + - rect: [490, 50, 200, 200] radius: { top-left: [32, 16], top-right: [40, 24], diff --git a/wrench/reftests/border/degenerate-curve.yaml b/wrench/reftests/border/degenerate-curve.yaml index a01bba4539..6e1c467488 100644 --- a/wrench/reftests/border/degenerate-curve.yaml +++ b/wrench/reftests/border/degenerate-curve.yaml @@ -9,7 +9,7 @@ root: "transform-style": flat items: - type: clip - bounds: [0, 0, 1000, 1000] + bounds: [28, 18, 144, 122] complex: - rect: [28, 18, 144, 122] radius: @@ -38,7 +38,7 @@ root: "bottom-left": [0, 0] "bottom-right": [61, 61] - type: clip - bounds: [0, 0, 1000, 1000] + bounds: [28, 160, 144, 122] complex: - rect: [28, 160, 144, 122] radius: [61, 61] @@ -60,7 +60,7 @@ root: - none radius: [61, 61] - type: clip - bounds: [0, 0, 1000, 1000] + bounds: [28, 302, 154, 122] complex: - rect: [28, 302, 154, 122] radius: @@ -93,7 +93,7 @@ root: "bottom-left": [0, 0] "bottom-right": [61, 61] - type: clip - bounds: [0, 0, 1000, 1000] + bounds: [202, 18, 145, 122] complex: - rect: [202, 18, 144.03334, 122] radius: @@ -124,7 +124,7 @@ root: - type: clip bounds: [202, 160, 144, 122] complex: - - rect: [0, 0, 144, 122] + - rect: [202, 160, 144, 122] radius: [61, 61] items: - type: rect @@ -145,7 +145,7 @@ root: - type: clip bounds: [202, 302, 154, 122] complex: - - rect: [0, 0, 154, 122] + - rect: [202, 302, 154, 122] radius: "top-left": [0, 0] "top-right": [72, 72] @@ -179,7 +179,7 @@ root: - type: clip bounds: [376, 18, 144, 122] complex: - - rect: [0, 0, 144, 122] + - rect: [376, 18, 144, 122] radius: [61, 61] items: - type: rect @@ -205,7 +205,7 @@ root: - type: clip bounds: [376, 160, 144, 122] complex: - - rect: [0, 0, 144, 122] + - rect: [376, 160, 144, 122] radius: [61, 61] items: - type: rect @@ -232,7 +232,7 @@ root: - type: clip bounds: [376, 302, 144, 122] complex: - - rect: [0, 0, 144, 122] + - rect: [376, 302, 144, 122] radius: "top-left": [0, 0] "top-right": [72, 72] diff --git a/wrench/reftests/scrolling/scroll-layer-with-mask.yaml b/wrench/reftests/scrolling/scroll-layer-with-mask.yaml index 66b661df31..dc4ee4410f 100644 --- a/wrench/reftests/scrolling/scroll-layer-with-mask.yaml +++ b/wrench/reftests/scrolling/scroll-layer-with-mask.yaml @@ -30,7 +30,7 @@ root: scroll-offset: [0, 100] image-mask: image: "mask.png" - rect: [0, 0, 100, 100] + rect: [10, 10, 100, 100] repeat: false items: - type: rect @@ -46,7 +46,7 @@ root: scroll-offset: [0, 100] image-mask: image: "mask.png" - rect: [0, 0, 100, 100] + rect: [210, 10, 100, 100] repeat: false items: - type: rect diff --git a/wrench/src/yaml_frame_reader.rs b/wrench/src/yaml_frame_reader.rs index 513b171be2..7c2407ac43 100644 --- a/wrench/src/yaml_frame_reader.rs +++ b/wrench/src/yaml_frame_reader.rs @@ -572,10 +572,9 @@ impl YamlFrameReader { } pub fn handle_scroll_frame(&mut self, wrench: &mut Wrench, yaml: &Yaml) { - let bounds = yaml["bounds"].as_rect().expect("clip must have a bounds"); - let content_size = yaml["content-size"].as_size().unwrap_or(bounds.size); - let content_rect = LayerRect::new(bounds.origin, content_size); - let clip_rect = LayerRect::new(LayerPoint::zero(), bounds.size); + let clip_rect = yaml["bounds"].as_rect().expect("clip must have a bounds"); + let content_size = yaml["content-size"].as_size().unwrap_or(clip_rect.size); + let content_rect = LayerRect::new(clip_rect.origin, content_size); let id = yaml["id"].as_i64().map(|id| ClipId::new(id as u64, self.builder().pipeline_id)); let complex_clips = self.to_complex_clip_regions(&yaml["complex"]); diff --git a/wrench/src/yaml_frame_writer.rs b/wrench/src/yaml_frame_writer.rs index 4c67dd1670..2c983ec003 100644 --- a/wrench/src/yaml_frame_writer.rs +++ b/wrench/src/yaml_frame_writer.rs @@ -747,7 +747,7 @@ impl YamlFrameWriter { Clip(item) => { str_node(&mut v, "type", "clip"); usize_node(&mut v, "id", clip_id_mapper.add_id(item.id)); - size_node(&mut v, "content-size", &item.content_rect.size); + size_node(&mut v, "content-size", &base.rect().size); let &(complex_clips, complex_clip_count) = base.complex_clip(); if let Some(complex) = self.make_clip_complex_node(complex_clip_count, @@ -763,7 +763,8 @@ impl YamlFrameWriter { ScrollFrame(item) => { str_node(&mut v, "type", "scroll-frame"); usize_node(&mut v, "id", clip_id_mapper.add_id(item.id)); - size_node(&mut v, "content-size", &item.content_rect.size); + size_node(&mut v, "content-size", &base.rect().size); + rect_node(&mut v, "bounds", &base.clip_rect()); let &(complex_clips, complex_clip_count) = base.complex_clip(); if let Some(complex) = self.make_clip_complex_node(complex_clip_count, From 5066a13879dc716d526b62a92209d39967c58a84 Mon Sep 17 00:00:00 2001 From: Martin Robinson Date: Wed, 28 Jun 2017 15:32:47 -0700 Subject: [PATCH 3/4] Add rounded rectangles for local clip This is a slight revert of the removal of per-item complex clips, but these clips are important for Servo. --- webrender/examples/animation.rs | 4 +- webrender/examples/basic.rs | 15 +-- webrender/examples/blob.rs | 4 +- webrender/examples/nested_display_list.rs | 14 +-- webrender/examples/scrolling.rs | 27 ++-- webrender/examples/yuv.rs | 4 +- webrender/src/border.rs | 20 +-- webrender/src/clip_scroll_node.rs | 28 +---- webrender/src/frame.rs | 142 +++++++++------------- webrender/src/frame_builder.rs | 72 +++++------ webrender/src/mask_cache.rs | 38 +++--- webrender_api/src/display_item.rs | 24 +++- webrender_api/src/display_list.rs | 64 +++++----- wrench/src/yaml_frame_reader.rs | 57 +++++---- wrench/src/yaml_frame_writer.rs | 34 ++++-- 15 files changed, 265 insertions(+), 282 deletions(-) diff --git a/webrender/examples/animation.rs b/webrender/examples/animation.rs index 0fe3ea0afc..77b0b89368 100644 --- a/webrender/examples/animation.rs +++ b/webrender/examples/animation.rs @@ -36,9 +36,7 @@ fn body(_api: &RenderApi, Vec::new()); // Fill it with a white rect - builder.push_rect(bounds, - bounds, - ColorF::new(1.0, 1.0, 1.0, 1.0)); + builder.push_rect(bounds, None, ColorF::new(1.0, 1.0, 1.0, 1.0)); builder.pop_stacking_context(); } diff --git a/webrender/examples/basic.rs b/webrender/examples/basic.rs index 45f4a05cd1..a65f95d7f8 100644 --- a/webrender/examples/basic.rs +++ b/webrender/examples/basic.rs @@ -201,12 +201,10 @@ fn body(api: &RenderApi, builder.push_clip_id(id); let bounds = (100, 100).to(200, 200); - builder.push_rect(bounds, bounds, ColorF::new(0.0, 1.0, 0.0, 1.0)); + builder.push_rect(bounds, None, ColorF::new(0.0, 1.0, 0.0, 1.0)); let bounds = (250, 100).to(350, 200); - builder.push_rect(bounds, - bounds, - ColorF::new(0.0, 1.0, 0.0, 1.0)); + builder.push_rect(bounds, None, ColorF::new(0.0, 1.0, 0.0, 1.0)); let border_side = BorderSide { color: ColorF::new(0.0, 0.0, 1.0, 1.0), style: BorderStyle::Groove, @@ -226,10 +224,7 @@ fn body(api: &RenderApi, }); let bounds = (100, 100).to(200, 200); - builder.push_border(bounds, - bounds, - border_widths, - border_details); + builder.push_border(bounds, None, border_widths, border_details); if false { // draw text? @@ -290,7 +285,7 @@ fn body(api: &RenderApi, ]; builder.push_text(text_bounds, - text_bounds, + None, &glyphs, font_key, ColorF::new(1.0, 1.0, 0.0, 1.0), @@ -310,7 +305,7 @@ fn body(api: &RenderApi, let box_shadow_type = BoxShadowClipMode::Inset; builder.push_box_shadow(rect, - bounds, + Some(LocalClip::from(bounds)), simple_box_bounds, offset, color, diff --git a/webrender/examples/blob.rs b/webrender/examples/blob.rs index 189f73e42f..de1fde1d0a 100644 --- a/webrender/examples/blob.rs +++ b/webrender/examples/blob.rs @@ -243,7 +243,7 @@ fn body(api: &api::RenderApi, builder.push_image( (30, 30).by(500, 500), - bounds, + Some(api::LocalClip::from(bounds)), api::LayoutSize::new(500.0, 500.0), api::LayoutSize::new(0.0, 0.0), api::ImageRendering::Auto, @@ -252,7 +252,7 @@ fn body(api: &api::RenderApi, builder.push_image( (600, 600).by(200, 200), - bounds, + Some(api::LocalClip::from(bounds)), api::LayoutSize::new(200.0, 200.0), api::LayoutSize::new(0.0, 0.0), api::ImageRendering::Auto, diff --git a/webrender/examples/nested_display_list.rs b/webrender/examples/nested_display_list.rs index 4998c5d72d..755c3b7f40 100644 --- a/webrender/examples/nested_display_list.rs +++ b/webrender/examples/nested_display_list.rs @@ -30,9 +30,7 @@ fn body(_api: &RenderApi, Vec::new()); let outer_scroll_frame_rect = (100, 100).to(600, 400); - builder.push_rect(outer_scroll_frame_rect, - outer_scroll_frame_rect, - ColorF::new(1.0, 1.0, 1.0, 1.0)); + builder.push_rect(outer_scroll_frame_rect, None, ColorF::new(1.0, 1.0, 1.0, 1.0)); let nested_clip_id = builder.define_scroll_frame(None, (100, 100).to(1000, 1000), @@ -45,7 +43,7 @@ fn body(_api: &RenderApi, let mut builder3 = DisplayListBuilder::new(*pipeline_id, *layout_size); let rect = (110, 110).to(210, 210); - builder3.push_rect(rect, rect, ColorF::new(0.0, 1.0, 0.0, 1.0)); + builder3.push_rect(rect, None, ColorF::new(0.0, 1.0, 0.0, 1.0)); // A fixed position rectangle should be fixed to the reference frame that starts // in the outer display list. @@ -57,16 +55,14 @@ fn body(_api: &RenderApi, MixBlendMode::Normal, Vec::new()); let rect = (0, 0).to(100, 100); - builder3.push_rect(rect, rect, ColorF::new(0.0, 1.0, 0.0, 1.0)); + builder3.push_rect(rect, None, ColorF::new(0.0, 1.0, 0.0, 1.0)); builder3.pop_stacking_context(); // Now we push an inner scroll frame that should have the same id as the outer one, // but the WebRender nested display list replacement code should convert it into // a unique ClipId. let inner_scroll_frame_rect = (330, 110).to(530, 360); - builder3.push_rect(inner_scroll_frame_rect, - inner_scroll_frame_rect, - ColorF::new(1.0, 0.0, 1.0, 0.5)); + builder3.push_rect(inner_scroll_frame_rect, None, ColorF::new(1.0, 0.0, 1.0, 0.5)); let inner_nested_clip_id = builder3.define_scroll_frame(None, (330, 110).to(2000, 2000), inner_scroll_frame_rect, @@ -74,7 +70,7 @@ fn body(_api: &RenderApi, None); builder3.push_clip_id(inner_nested_clip_id); let rect = (340, 120).to(440, 220); - builder3.push_rect(rect, rect, ColorF::new(0.0, 1.0, 0.0, 1.0)); + builder3.push_rect(rect, None, ColorF::new(0.0, 1.0, 0.0, 1.0)); builder3.pop_clip_id(); let (_, _, built_list) = builder3.finalize(); diff --git a/webrender/examples/scrolling.rs b/webrender/examples/scrolling.rs index d83b8ab687..9052327c2b 100644 --- a/webrender/examples/scrolling.rs +++ b/webrender/examples/scrolling.rs @@ -50,17 +50,15 @@ fn body(_api: &RenderApi, // now put some content into it. // start with a white background - builder.push_rect((0, 0).to(1000, 1000), - (0, 0).to(1000, 1000), - ColorF::new(1.0, 1.0, 1.0, 1.0)); + builder.push_rect((0, 0).to(1000, 1000), None, ColorF::new(1.0, 1.0, 1.0, 1.0)); + // let's make a 50x50 blue square as a visual reference - builder.push_rect((0, 0).to(50, 50), - (0, 0).to(50, 50), - ColorF::new(0.0, 0.0, 1.0, 1.0)); + builder.push_rect((0, 0).to(50, 50), None, ColorF::new(0.0, 0.0, 1.0, 1.0)); + // and a 50x50 green square next to it with an offset clip // to see what that looks like builder.push_rect((50, 0).to(100, 50), - (60, 10).to(110, 60), + Some(LocalClip::from((60, 10).to(110, 60))), ColorF::new(0.0, 1.0, 0.0, 1.0)); // Below the above rectangles, set up a nested scrollbox. It's still in @@ -75,20 +73,17 @@ fn body(_api: &RenderApi, // give it a giant gray background just to distinguish it and to easily // visually identify the nested scrollbox - builder.push_rect((-1000, -1000).to(5000, 5000), - (-1000, -1000).to(5000, 5000), - ColorF::new(0.5, 0.5, 0.5, 1.0)); + builder.push_rect((-1000, -1000).to(5000, 5000), None, ColorF::new(0.5, 0.5, 0.5, 1.0)); + // add a teal square to visualize the scrolling/clipping behaviour // as you scroll the nested scrollbox with WASD keys - builder.push_rect((0, 100).to(50, 150), - (0, 100).to(50, 150), - ColorF::new(0.0, 1.0, 1.0, 1.0)); + builder.push_rect((0, 100).to(50, 150), None, ColorF::new(0.0, 1.0, 1.0, 1.0)); + // just for good measure add another teal square in the bottom-right // corner of the nested scrollframe content, which can be scrolled into // view by the user - builder.push_rect((250, 350).to(300, 400), - (250, 350).to(300, 400), - ColorF::new(0.0, 1.0, 1.0, 1.0)); + builder.push_rect((250, 350).to(300, 400), None, ColorF::new(0.0, 1.0, 1.0, 1.0)); + builder.pop_clip_id(); // nested_clip_id builder.pop_clip_id(); // clip_id diff --git a/webrender/examples/yuv.rs b/webrender/examples/yuv.rs index 56b193c370..4f4a70d0eb 100644 --- a/webrender/examples/yuv.rs +++ b/webrender/examples/yuv.rs @@ -206,7 +206,7 @@ fn body(api: &RenderApi, builder.push_yuv_image( LayoutRect::new(LayoutPoint::new(100.0, 0.0), LayoutSize::new(100.0, 100.0)), - bounds, + Some(LocalClip::from(bounds)), YuvData::NV12(yuv_chanel1, yuv_chanel2), YuvColorSpace::Rec601, ImageRendering::Auto, @@ -214,7 +214,7 @@ fn body(api: &RenderApi, builder.push_yuv_image( LayoutRect::new(LayoutPoint::new(300.0, 0.0), LayoutSize::new(100.0, 100.0)), - bounds, + Some(LocalClip::from(bounds)), YuvData::PlanarYCbCr(yuv_chanel1, yuv_chanel2_1, yuv_chanel3), YuvColorSpace::Rec601, ImageRendering::Auto, diff --git a/webrender/src/border.rs b/webrender/src/border.rs index 0184b6e013..5603344b31 100644 --- a/webrender/src/border.rs +++ b/webrender/src/border.rs @@ -2,6 +2,8 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +use api::{BorderSide, BorderStyle, BorderWidths, ClipAndScrollInfo, ColorF, LayerPoint, LayerRect}; +use api::{LayerSize, LocalClip, NormalBorder}; use ellipse::Ellipse; use gpu_cache::GpuDataRequest; use frame_builder::FrameBuilder; @@ -9,8 +11,6 @@ use mask_cache::ClipSource; use prim_store::{BorderPrimitiveCpu, PrimitiveContainer}; use tiling::PrimitiveFlags; use util::{lerp, pack_as_float}; -use api::{BorderSide, BorderStyle, BorderWidths, ClipAndScrollInfo, ColorF}; -use api::{LayerPoint, LayerRect, LayerSize, NormalBorder}; #[repr(u8)] #[derive(Debug, Copy, Clone, PartialEq)] @@ -226,7 +226,7 @@ impl FrameBuilder { border: &NormalBorder, widths: &BorderWidths, clip_and_scroll: ClipAndScrollInfo, - clip_rect: &LayerRect, + local_clip: &LocalClip, corner_instances: [BorderCornerInstance; 4], extra_clips: &[ClipSource]) { let radius = &border.radius; @@ -273,7 +273,7 @@ impl FrameBuilder { self.add_primitive(clip_and_scroll, &rect, - clip_rect, + local_clip, extra_clips, PrimitiveContainer::Border(prim_cpu)); } @@ -287,7 +287,7 @@ impl FrameBuilder { border: &NormalBorder, widths: &BorderWidths, clip_and_scroll: ClipAndScrollInfo, - clip_rect: &LayerRect) { + local_clip: &LocalClip) { // The border shader is quite expensive. For simple borders, we can just draw // the border with a few rectangles. This generally gives better batching, and // a GPU win in fragment shader time. @@ -367,7 +367,7 @@ impl FrameBuilder { if top_edge == BorderEdgeKind::Solid { self.add_solid_rectangle(clip_and_scroll, &LayerRect::new(p0, LayerSize::new(rect_width, top_len)), - clip_rect, + local_clip, &border.top.color, PrimitiveFlags::None); } @@ -376,7 +376,7 @@ impl FrameBuilder { &LayerRect::new(LayerPoint::new(p0.x, p0.y + top_len), LayerSize::new(left_len, rect_height - top_len - bottom_len)), - clip_rect, + local_clip, &border.left.color, PrimitiveFlags::None); } @@ -386,7 +386,7 @@ impl FrameBuilder { p0.y + top_len), LayerSize::new(right_len, rect_height - top_len - bottom_len)), - clip_rect, + local_clip, &border.right.color, PrimitiveFlags::None); } @@ -394,7 +394,7 @@ impl FrameBuilder { self.add_solid_rectangle(clip_and_scroll, &LayerRect::new(LayerPoint::new(p0.x, p1.y - bottom_len), LayerSize::new(rect_width, bottom_len)), - clip_rect, + local_clip, &border.bottom.color, PrimitiveFlags::None); } @@ -423,7 +423,7 @@ impl FrameBuilder { border, widths, clip_and_scroll, - clip_rect, + local_clip, corner_instances, &extra_clips); } diff --git a/webrender/src/clip_scroll_node.rs b/webrender/src/clip_scroll_node.rs index 6d2768ff90..0b78d1532c 100644 --- a/webrender/src/clip_scroll_node.rs +++ b/webrender/src/clip_scroll_node.rs @@ -9,7 +9,7 @@ use geometry::ray_intersects_rect; use mask_cache::{ClipRegion, ClipSource, MaskCacheInfo}; use spring::{DAMPING, STIFFNESS, Spring}; use tiling::PackedLayerIndex; -use util::{ComplexClipRegionHelpers, MatrixHelpers, TransformedRectKind}; +use util::{MatrixHelpers, TransformedRectKind}; #[cfg(target_os = "macos")] const CAN_OVERSCROLL: bool = true; @@ -393,32 +393,6 @@ impl ClipScrollNode { _ => false, } } - - pub fn find_unclipped_rectangle(&self, rect: &LayerRect) -> Option { - let clip_sources = match self.node_type { - NodeType::Clip(ref clip_info) => &clip_info.clip_sources, - _ => return None, - }; - - let clip_region = match clip_sources.last() { - Some(&ClipSource::Region(ref clip_region)) if clip_sources.len() == 1 => clip_region, - _ => return None, - }; - - if clip_region.image_mask.is_some() || clip_region.complex_clips.is_empty() { - return None; - } - - let offset = &self.local_viewport_rect.origin.to_vector(); - let base_rect = clip_region.main.translate(offset).intersection(rect); - clip_region.complex_clips.iter().fold(base_rect, |inner_combined, ccr| { - inner_combined.and_then(|combined| { - ccr.get_inner_rect_full().and_then(|ir| { - ir.translate(offset).intersection(&combined) - }) - }) - }) - } } #[derive(Copy, Clone, Debug)] diff --git a/webrender/src/frame.rs b/webrender/src/frame.rs index 526020dfcf..bd450642bd 100644 --- a/webrender/src/frame.rs +++ b/webrender/src/frame.rs @@ -3,12 +3,11 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use api::{BuiltDisplayList, BuiltDisplayListIter, ClipAndScrollInfo, ClipId, ColorF}; -use api::{ComplexClipRegion, DeviceUintRect, DeviceUintSize, DisplayItemRef, Epoch}; -use api::{FilterOp, ImageDisplayItem, ItemRange, LayerPoint, LayerRect, LayerSize}; -use api::{LayerToScrollTransform, LayerVector2D, LayoutSize, LayoutTransform}; -use api::{MixBlendMode, PipelineId, ScrollClamping, ScrollEventPhase}; -use api::{ScrollLayerState, ScrollLocation, ScrollPolicy, SpecificDisplayItem}; -use api::{StackingContext, TileOffset, TransformStyle, WorldPoint}; +use api::{ComplexClipRegion, DeviceUintRect, DeviceUintSize, DisplayItemRef, Epoch, FilterOp}; +use api::{ImageDisplayItem, ItemRange, LayerPoint, LayerRect, LayerSize, LayerToScrollTransform}; +use api::{LayerVector2D, LayoutSize, LayoutTransform, LocalClip, MixBlendMode, PipelineId}; +use api::{ScrollClamping, ScrollEventPhase, ScrollLayerState, ScrollLocation, ScrollPolicy}; +use api::{SpecificDisplayItem, StackingContext, TileOffset, TransformStyle, WorldPoint}; use app_units::Au; use clip_scroll_tree::{ClipScrollTree, ScrollStates}; use euclid::rect; @@ -26,7 +25,7 @@ use std::cmp; use std::collections::HashMap; use std::hash::BuildHasherDefault; use tiling::{CompositeOps, DisplayListMap, PrimitiveFlags}; -use util::subtract_rect; +use util::{ComplexClipRegionHelpers, subtract_rect}; #[derive(Copy, Clone, PartialEq, PartialOrd, Debug)] pub struct FrameId(pub u32); @@ -541,7 +540,7 @@ impl Frame { SpecificDisplayItem::WebGL(ref info) => { context.builder.add_webgl_rectangle(clip_and_scroll, item.rect(), - item.clip_rect(), + item.local_clip(), info.context_id); } SpecificDisplayItem::Image(ref info) => { @@ -554,14 +553,14 @@ impl Frame { self.decompose_image(clip_and_scroll, context, &item.rect(), - item.clip_rect(), + item.local_clip(), info, image_size, tile_size as u32); } else { context.builder.add_image(clip_and_scroll, item.rect(), - item.clip_rect(), + item.local_clip(), &info.stretch_size, &info.tile_spacing, None, @@ -573,7 +572,7 @@ impl Frame { SpecificDisplayItem::YuvImage(ref info) => { context.builder.add_yuv_image(clip_and_scroll, item.rect(), - item.clip_rect(), + item.local_clip(), info.yuv_data, info.color_space, info.image_rendering); @@ -581,7 +580,7 @@ impl Frame { SpecificDisplayItem::Text(ref text_info) => { context.builder.add_text(clip_and_scroll, item.rect(), - item.clip_rect(), + item.local_clip(), text_info.font_key, text_info.size, text_info.blur_radius, @@ -593,13 +592,12 @@ impl Frame { SpecificDisplayItem::Rectangle(ref info) => { if !self.try_to_add_rectangle_splitting_on_clip(context, &item.rect(), - item.clip_rect(), + item.local_clip(), &info.color, - &clip_and_scroll, - &reference_frame_relative_offset) { + &clip_and_scroll) { context.builder.add_solid_rectangle(clip_and_scroll, &item.rect(), - item.clip_rect(), + item.local_clip(), &info.color, PrimitiveFlags::None); @@ -608,7 +606,7 @@ impl Frame { SpecificDisplayItem::Gradient(ref info) => { context.builder.add_gradient(clip_and_scroll, item.rect(), - item.clip_rect(), + item.local_clip(), info.gradient.start_point, info.gradient.end_point, item.gradient_stops(), @@ -621,7 +619,7 @@ impl Frame { SpecificDisplayItem::RadialGradient(ref info) => { context.builder.add_radial_gradient(clip_and_scroll, item.rect(), - item.clip_rect(), + item.local_clip(), info.gradient.start_center, info.gradient.start_radius, info.gradient.end_center, @@ -635,7 +633,7 @@ impl Frame { SpecificDisplayItem::BoxShadow(ref box_shadow_info) => { context.builder.add_box_shadow(clip_and_scroll, &box_shadow_info.box_bounds, - item.clip_rect(), + item.local_clip(), &box_shadow_info.offset, &box_shadow_info.color, box_shadow_info.blur_radius, @@ -646,7 +644,7 @@ impl Frame { SpecificDisplayItem::Border(ref info) => { context.builder.add_border(clip_and_scroll, item.rect(), - item.clip_rect(), + item.local_clip(), info, item.gradient_stops(), item.display_list() @@ -673,9 +671,9 @@ impl Frame { } SpecificDisplayItem::Clip(ref info) => { let complex_clips = context.get_complex_clips(pipeline_id, item.complex_clip().0); - let mut clip_region = ClipRegion::new(*item.clip_rect(), - info.image_mask, - complex_clips); + let mut clip_region = ClipRegion::for_clip_node(*item.local_clip().clip_rect(), + complex_clips, + info.image_mask); clip_region.origin += reference_frame_relative_offset; self.flatten_clip(context, @@ -686,15 +684,17 @@ impl Frame { } SpecificDisplayItem::ScrollFrame(ref info) => { let complex_clips = context.get_complex_clips(pipeline_id, item.complex_clip().0); - let mut clip_region = ClipRegion::new(*item.clip_rect(), - info.image_mask, - complex_clips); + let mut clip_region = ClipRegion::for_clip_node(*item.local_clip().clip_rect(), + complex_clips, + info.image_mask); clip_region.origin += reference_frame_relative_offset; // Just use clip rectangle as the frame rect for this scroll frame. // This is only interesting when calculating scroll extents for the // ClipScrollNode::scroll(..) API - let frame_rect = item.clip_rect().translate(&reference_frame_relative_offset); + let frame_rect = item.local_clip() + .clip_rect() + .translate(&reference_frame_relative_offset); let content_rect = item.rect().translate(&reference_frame_relative_offset); self.flatten_scroll_frame(context, pipeline_id, @@ -729,10 +729,9 @@ impl Frame { fn try_to_add_rectangle_splitting_on_clip(&mut self, context: &mut FlattenContext, rect: &LayerRect, - clip_rect: &LayerRect, + local_clip: &LocalClip, color: &ColorF, - clip_and_scroll: &ClipAndScrollInfo, - reference_frame_relative_offset: &LayerVector2D) + clip_and_scroll: &ClipAndScrollInfo) -> bool { // If this rectangle is not opaque, splitting the rectangle up // into an inner opaque region just ends up hurting batching and @@ -741,68 +740,37 @@ impl Frame { return false; } - let (unclipped_rect, parent_clip_and_scroll) = - match self.find_unclipped_rectangle(clip_and_scroll, - rect, - reference_frame_relative_offset) { - Some((rect, clip_and_scroll)) => (rect, clip_and_scroll), + let inner_unclipped_rect = match local_clip { + &LocalClip::Rect(_) => return false, + &LocalClip::RoundedRect(_, ref region) => region.get_inner_rect_full(), + }; + let inner_unclipped_rect = match inner_unclipped_rect { + Some(rect) => rect, None => return false, }; - // The inner rectangle is not clipped by its assigned clipping node, so we can // let it be clipped by the parent of the clipping node, which may result in // less masking some cases. let mut clipped_rects = Vec::new(); - subtract_rect(rect, &unclipped_rect, &mut clipped_rects); + subtract_rect(rect, &inner_unclipped_rect, &mut clipped_rects); - context.builder.add_solid_rectangle(parent_clip_and_scroll, - &unclipped_rect, - clip_rect, + context.builder.add_solid_rectangle(*clip_and_scroll, + &inner_unclipped_rect, + &LocalClip::from(*local_clip.clip_rect()), color, PrimitiveFlags::None); for clipped_rect in &clipped_rects { context.builder.add_solid_rectangle(*clip_and_scroll, clipped_rect, - clip_rect, + local_clip, color, PrimitiveFlags::None); } true } - fn find_unclipped_rectangle(&mut self, - clip_and_scroll: &ClipAndScrollInfo, - rect: &LayerRect, - reference_frame_relative_offset: &LayerVector2D) - -> Option<(LayerRect, ClipAndScrollInfo)> { - // Try to extract the opaque inner rectangle out of the clipped primitive. - if clip_and_scroll.scroll_node_id != clip_and_scroll.clip_node_id() { - return None; - } - - let clip_node = match self.clip_scroll_tree.nodes.get(&clip_and_scroll.scroll_node_id) { - Some(node) => node, - None => return None, - }; - - let parent_node_id = match clip_node.parent { - Some(id) => id, - None => return None, - }; - - let rect_in_reference_frame = rect.translate(reference_frame_relative_offset); - let unclipped_rect = match clip_node.find_unclipped_rectangle(&rect_in_reference_frame) { - Some(rect) => rect, - None => return None, - }; - - let mut new_clip_and_scroll = *clip_and_scroll; - new_clip_and_scroll.clip_node_id = Some(parent_node_id); - Some((unclipped_rect, new_clip_and_scroll)) - } - fn flatten_root<'a>(&mut self, traversal: &mut BuiltDisplayListIter<'a>, pipeline_id: PipelineId, @@ -828,7 +796,7 @@ impl Frame { let root_bounds = LayerRect::new(LayerPoint::zero(), *content_size); context.builder.add_solid_rectangle(ClipAndScrollInfo::simple(clip_id), &root_bounds, - &root_bounds, + &LocalClip::from(root_bounds), &bg_color, PrimitiveFlags::None); } @@ -843,7 +811,7 @@ impl Frame { context.builder.add_solid_rectangle( ClipAndScrollInfo::simple(clip_id), &scrollbar_rect, - &scrollbar_rect, + &LocalClip::from(scrollbar_rect), &DEFAULT_SCROLLBAR_COLOR, PrimitiveFlags::Scrollbar(self.clip_scroll_tree.topmost_scrolling_node_id(), 4.0)); } @@ -893,7 +861,7 @@ impl Frame { clip_and_scroll: ClipAndScrollInfo, context: &mut FlattenContext, item_rect: &LayerRect, - item_clip_rect: &LayerRect, + item_local_clip: &LocalClip, info: &ImageDisplayItem, image_size: DeviceUintSize, tile_size: u32) { @@ -903,7 +871,7 @@ impl Frame { self.decompose_image_row(clip_and_scroll, context, item_rect, - item_clip_rect, + item_local_clip, info, image_size, tile_size); @@ -923,7 +891,7 @@ impl Frame { self.decompose_image_row(clip_and_scroll, context, &row_rect, - item_clip_rect, + item_local_clip, info, image_size, tile_size); @@ -935,7 +903,7 @@ impl Frame { clip_and_scroll: ClipAndScrollInfo, context: &mut FlattenContext, item_rect: &LayerRect, - item_clip_rect: &LayerRect, + item_local_clip: &LocalClip, info: &ImageDisplayItem, image_size: DeviceUintSize, tile_size: u32) { @@ -945,7 +913,7 @@ impl Frame { self.decompose_tiled_image(clip_and_scroll, context, item_rect, - item_clip_rect, + item_local_clip, info, image_size, tile_size); @@ -965,7 +933,7 @@ impl Frame { self.decompose_tiled_image(clip_and_scroll, context, &decomposed_rect, - item_clip_rect, + item_local_clip, info, image_size, tile_size); @@ -977,7 +945,7 @@ impl Frame { clip_and_scroll: ClipAndScrollInfo, context: &mut FlattenContext, item_rect: &LayerRect, - item_clip_rect: &LayerRect, + item_local_clip: &LocalClip, info: &ImageDisplayItem, image_size: DeviceUintSize, tile_size: u32) { @@ -1056,7 +1024,7 @@ impl Frame { self.add_tile_primitive(clip_and_scroll, context, item_rect, - item_clip_rect, + item_local_clip, info, TileOffset::new(tx, ty), stretched_tile_size, @@ -1068,7 +1036,7 @@ impl Frame { self.add_tile_primitive(clip_and_scroll, context, item_rect, - item_clip_rect, + item_local_clip, info, TileOffset::new(num_tiles_x, ty), stretched_tile_size, @@ -1084,7 +1052,7 @@ impl Frame { self.add_tile_primitive(clip_and_scroll, context, item_rect, - item_clip_rect, + item_local_clip, info, TileOffset::new(tx, num_tiles_y), stretched_tile_size, @@ -1099,7 +1067,7 @@ impl Frame { self.add_tile_primitive(clip_and_scroll, context, item_rect, - item_clip_rect, + item_local_clip, info, TileOffset::new(num_tiles_x, num_tiles_y), stretched_tile_size, @@ -1115,7 +1083,7 @@ impl Frame { clip_and_scroll: ClipAndScrollInfo, context: &mut FlattenContext, item_rect: &LayerRect, - item_clip_rect: &LayerRect, + item_local_clip: &LocalClip, info: &ImageDisplayItem, tile_offset: TileOffset, stretched_tile_size: LayerSize, @@ -1159,7 +1127,7 @@ impl Frame { if let Some(prim_rect) = prim_rect.intersection(item_rect) { context.builder.add_image(clip_and_scroll, prim_rect, - item_clip_rect, + item_local_clip, &stretched_size, &info.tile_spacing, None, diff --git a/webrender/src/frame_builder.rs b/webrender/src/frame_builder.rs index 10624f435f..db5947328e 100644 --- a/webrender/src/frame_builder.rs +++ b/webrender/src/frame_builder.rs @@ -2,11 +2,11 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -use api::{BorderDetails, BorderDisplayItem, BoxShadowClipMode, ClipAndScrollInfo, ClipId}; -use api::{ClipRegion, ColorF, DeviceIntPoint, DeviceIntRect, DeviceIntSize, DeviceUintRect}; -use api::{DeviceUintSize, ExtendMode, FontKey, FontRenderMode, GlyphInstance, GlyphOptions}; -use api::{GradientStop, ImageKey, ImageRendering, ItemRange, LayerPoint, LayerRect, LayerSize}; -use api::{LayerToScrollTransform, LayerVector2D, PipelineId, RepeatMode, TileOffset}; +use api::{BorderDetails, BorderDisplayItem, BoxShadowClipMode, ClipAndScrollInfo, ClipId, ColorF}; +use api::{DeviceIntPoint, DeviceIntRect, DeviceIntSize, DeviceUintRect, DeviceUintSize}; +use api::{ExtendMode, FontKey, FontRenderMode, GlyphInstance, GlyphOptions, GradientStop}; +use api::{ImageKey, ImageRendering, ItemRange, LayerPoint, LayerRect, LayerSize}; +use api::{LayerToScrollTransform, LayerVector2D, LocalClip, PipelineId, RepeatMode, TileOffset}; use api::{TransformStyle, WebGLContextId, WorldPixel, YuvColorSpace, YuvData}; use app_units::Au; use frame::FrameId; @@ -188,7 +188,7 @@ impl FrameBuilder { pub fn add_primitive(&mut self, clip_and_scroll: ClipAndScrollInfo, rect: &LayerRect, - clip_rect: &LayerRect, + local_clip: &LocalClip, extra_clips: &[ClipSource], container: PrimitiveContainer) -> PrimitiveIndex { @@ -196,7 +196,11 @@ impl FrameBuilder { self.create_clip_scroll_group_if_necessary(stacking_context_index, clip_and_scroll); - let clip_sources = extra_clips.to_vec(); + let mut clip_sources = extra_clips.to_vec(); + if let &LocalClip::RoundedRect(_, _) = local_clip { + clip_sources.push(ClipSource::Region(ClipRegion::for_local_clip(local_clip))) + } + let clip_info = if !clip_sources.is_empty() { Some(MaskCacheInfo::new(&clip_sources)) } else { @@ -204,7 +208,7 @@ impl FrameBuilder { }; let prim_index = self.prim_store.add_primitive(rect, - &clip_rect, + &local_clip.clip_rect(), clip_sources, clip_info, container); @@ -391,7 +395,7 @@ impl FrameBuilder { pub fn add_solid_rectangle(&mut self, clip_and_scroll: ClipAndScrollInfo, rect: &LayerRect, - clip_rect: &LayerRect, + local_clip: &LocalClip, color: &ColorF, flags: PrimitiveFlags) { if color.a == 0.0 { @@ -404,7 +408,7 @@ impl FrameBuilder { let prim_index = self.add_primitive(clip_and_scroll, rect, - clip_rect, + local_clip, &[], PrimitiveContainer::Rectangle(prim)); @@ -423,7 +427,7 @@ impl FrameBuilder { pub fn add_border(&mut self, clip_and_scroll: ClipAndScrollInfo, rect: LayerRect, - clip_rect: &LayerRect, + local_clip: &LocalClip, border_item: &BorderDisplayItem, gradient_stops: ItemRange, gradient_stops_count: usize) { @@ -570,7 +574,7 @@ impl FrameBuilder { for segment in segments { self.add_image(clip_and_scroll, segment.geom_rect, - clip_rect, + local_clip, &segment.stretch_size, &segment.tile_spacing, Some(segment.sub_rect), @@ -584,7 +588,7 @@ impl FrameBuilder { border, &border_item.widths, clip_and_scroll, - clip_rect); + local_clip); } BorderDetails::Gradient(ref border) => { for segment in create_segments(border.outset) { @@ -592,7 +596,7 @@ impl FrameBuilder { self.add_gradient(clip_and_scroll, segment, - clip_rect, + local_clip, border.gradient.start_point - segment_rel, border.gradient.end_point - segment_rel, gradient_stops, @@ -608,7 +612,7 @@ impl FrameBuilder { self.add_radial_gradient(clip_and_scroll, segment, - clip_rect, + local_clip, border.gradient.start_center - segment_rel, border.gradient.start_radius, border.gradient.end_center - segment_rel, @@ -626,7 +630,7 @@ impl FrameBuilder { pub fn add_gradient(&mut self, clip_and_scroll: ClipAndScrollInfo, rect: LayerRect, - clip_rect: &LayerRect, + local_clip: &LocalClip, start_point: LayerPoint, end_point: LayerPoint, stops: ItemRange, @@ -686,13 +690,13 @@ impl FrameBuilder { PrimitiveContainer::AngleGradient(gradient_cpu) }; - self.add_primitive(clip_and_scroll, &rect, clip_rect, &[], prim); + self.add_primitive(clip_and_scroll, &rect, local_clip, &[], prim); } pub fn add_radial_gradient(&mut self, clip_and_scroll: ClipAndScrollInfo, rect: LayerRect, - clip_rect: &LayerRect, + local_clip: &LocalClip, start_center: LayerPoint, start_radius: f32, end_center: LayerPoint, @@ -717,7 +721,7 @@ impl FrameBuilder { self.add_primitive(clip_and_scroll, &rect, - clip_rect, + local_clip, &[], PrimitiveContainer::RadialGradient(radial_gradient_cpu)); } @@ -725,7 +729,7 @@ impl FrameBuilder { pub fn add_text(&mut self, clip_and_scroll: ClipAndScrollInfo, rect: LayerRect, - clip_rect: &LayerRect, + local_clip: &LocalClip, font_key: FontKey, size: Au, blur_radius: f32, @@ -788,7 +792,7 @@ impl FrameBuilder { self.add_primitive(clip_and_scroll, &rect, - clip_rect, + local_clip, &[], PrimitiveContainer::TextRun(prim_cpu)); } @@ -797,7 +801,7 @@ impl FrameBuilder { clip_and_scroll: ClipAndScrollInfo, box_bounds: &LayerRect, bs_rect: LayerRect, - clip_rect: &LayerRect, + local_clip: &LocalClip, color: &ColorF, border_radius: f32, clip_mode: BoxShadowClipMode) { @@ -820,7 +824,7 @@ impl FrameBuilder { self.add_primitive(clip_and_scroll, &rect_to_draw, - clip_rect, + local_clip, &extra_clips, PrimitiveContainer::Rectangle(prim)); } @@ -828,7 +832,7 @@ impl FrameBuilder { pub fn add_box_shadow(&mut self, clip_and_scroll: ClipAndScrollInfo, box_bounds: &LayerRect, - clip_rect: &LayerRect, + local_clip: &LocalClip, box_offset: &LayerVector2D, color: &ColorF, blur_radius: f32, @@ -858,7 +862,7 @@ impl FrameBuilder { || bs_rect_empty { self.add_solid_rectangle(clip_and_scroll, box_bounds, - clip_rect, + local_clip, color, PrimitiveFlags::None); return; @@ -868,7 +872,7 @@ impl FrameBuilder { self.fill_box_shadow_rect(clip_and_scroll, box_bounds, bs_rect, - clip_rect, + local_clip, color, border_radius, clip_mode); @@ -941,7 +945,7 @@ impl FrameBuilder { for rect in &rects { self.add_solid_rectangle(clip_and_scroll, rect, - clip_rect, + local_clip, color, PrimitiveFlags::None) } @@ -952,7 +956,7 @@ impl FrameBuilder { self.fill_box_shadow_rect(clip_and_scroll, box_bounds, bs_rect, - clip_rect, + local_clip, color, border_radius, clip_mode); @@ -990,7 +994,7 @@ impl FrameBuilder { self.add_primitive(clip_and_scroll, &outer_rect, - clip_rect, + local_clip, extra_clips.as_slice(), PrimitiveContainer::BoxShadow(prim_cpu)); } @@ -1000,7 +1004,7 @@ impl FrameBuilder { pub fn add_webgl_rectangle(&mut self, clip_and_scroll: ClipAndScrollInfo, rect: LayerRect, - clip_rect: &LayerRect, + local_clip: &LocalClip, context_id: WebGLContextId) { let prim_cpu = ImagePrimitiveCpu { kind: ImagePrimitiveKind::WebGL(context_id), @@ -1010,7 +1014,7 @@ impl FrameBuilder { self.add_primitive(clip_and_scroll, &rect, - clip_rect, + local_clip, &[], PrimitiveContainer::Image(prim_cpu)); } @@ -1018,7 +1022,7 @@ impl FrameBuilder { pub fn add_image(&mut self, clip_and_scroll: ClipAndScrollInfo, rect: LayerRect, - clip_rect: &LayerRect, + local_clip: &LocalClip, stretch_size: &LayerSize, tile_spacing: &LayerSize, sub_rect: Option, @@ -1042,7 +1046,7 @@ impl FrameBuilder { self.add_primitive(clip_and_scroll, &rect, - clip_rect, + local_clip, &[], PrimitiveContainer::Image(prim_cpu)); } @@ -1050,7 +1054,7 @@ impl FrameBuilder { pub fn add_yuv_image(&mut self, clip_and_scroll: ClipAndScrollInfo, rect: LayerRect, - clip_rect: &LayerRect, + clip_rect: &LocalClip, yuv_data: YuvData, color_space: YuvColorSpace, image_rendering: ImageRendering) { diff --git a/webrender/src/mask_cache.rs b/webrender/src/mask_cache.rs index fb58352136..e77292eb13 100644 --- a/webrender/src/mask_cache.rs +++ b/webrender/src/mask_cache.rs @@ -2,15 +2,12 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -use api::{BorderRadius, ComplexClipRegion, DeviceIntRect, ImageMask, LayerPoint}; -use api::{LayerRect, LayerSize, LayerToWorldTransform}; +use api::{BorderRadius, ComplexClipRegion, DeviceIntRect, ImageMask, LayerPoint, LayerRect}; +use api::{LayerSize, LayerToWorldTransform, LocalClip}; use border::BorderCornerClipSource; use gpu_cache::{GpuCache, GpuCacheHandle, ToGpuBlocks}; use prim_store::{CLIP_DATA_GPU_BLOCKS, ClipData, ImageMaskData}; use util::{ComplexClipRegionHelpers, TransformedRect}; -use api::{BorderRadius, BuiltDisplayList, ClipRegion, ComplexClipRegion, ImageMask}; -use api::{DeviceIntRect, LayerToWorldTransform}; -use api::{LayerRect, LayerPoint, LayerSize}; use std::ops::Not; const MAX_CLIP: f32 = 1000000.0; @@ -24,29 +21,42 @@ pub struct ClipRegion { } impl ClipRegion { - pub fn new(main: LayerRect, - mut image_mask: Option, - mut complex_clips: Vec) - -> ClipRegion { - let negative_origin = -main.origin.to_vector(); - + pub fn for_clip_node(rect: LayerRect, + mut complex_clips: Vec, + mut image_mask: Option) + -> ClipRegion { // All the coordinates we receive are relative to the stacking context, but we want // to convert them to something relative to the origin of the clip. + let negative_origin = -rect.origin.to_vector(); if let Some(ref mut image_mask) = image_mask { image_mask.rect = image_mask.rect.translate(&negative_origin); } - for ref mut complex_clip in complex_clips.iter_mut() { + for complex_clip in complex_clips.iter_mut() { complex_clip.rect = complex_clip.rect.translate(&negative_origin); } ClipRegion { - origin: main.origin, - main: LayerRect::new(LayerPoint::zero(), main.size), + origin: rect.origin, + main: LayerRect::new(LayerPoint::zero(), rect.size), image_mask, complex_clips, } } + + pub fn for_local_clip(local_clip: &LocalClip) -> ClipRegion { + let complex_clips = match local_clip { + &LocalClip::Rect(_) => Vec::new(), + &LocalClip::RoundedRect(_, ref region) => vec![region.clone()], + }; + + ClipRegion { + origin: LayerPoint::zero(), + main: *local_clip.clip_rect(), + image_mask: None, + complex_clips, + } + } } #[repr(C)] diff --git a/webrender_api/src/display_item.rs b/webrender_api/src/display_item.rs index 2e984d28d0..dc1ded5710 100644 --- a/webrender_api/src/display_item.rs +++ b/webrender_api/src/display_item.rs @@ -42,7 +42,7 @@ impl ClipAndScrollInfo { pub struct DisplayItem { pub item: SpecificDisplayItem, pub rect: LayoutRect, - pub clip_rect: LayoutRect, + pub local_clip: LocalClip, pub clip_and_scroll: ClipAndScrollInfo, } @@ -447,6 +447,27 @@ pub struct ImageMask { pub repeat: bool, } +#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)] +pub enum LocalClip { + Rect(LayoutRect), + RoundedRect(LayoutRect, ComplexClipRegion), +} + +impl From for LocalClip { + fn from(rect: LayoutRect) -> Self { + LocalClip::Rect(rect) + } +} + +impl LocalClip { + pub fn clip_rect(&self) -> &LayoutRect { + match *self { + LocalClip::Rect(ref rect) => rect, + LocalClip::RoundedRect(ref rect, _) => &rect, + } + } +} + #[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)] pub struct ComplexClipRegion { /// The boundaries of the rectangle. @@ -615,3 +636,4 @@ define_empty_heap_size_of!(RepeatMode); define_empty_heap_size_of!(ImageKey); define_empty_heap_size_of!(MixBlendMode); define_empty_heap_size_of!(TransformStyle); +define_empty_heap_size_of!(LocalClip); diff --git a/webrender_api/src/display_list.rs b/webrender_api/src/display_list.rs index 8e6c90712d..26c4a0321c 100644 --- a/webrender_api/src/display_list.rs +++ b/webrender_api/src/display_list.rs @@ -11,8 +11,8 @@ use {BorderDetails, BorderDisplayItem, BorderWidths, BoxShadowClipMode, BoxShado use {ClipAndScrollInfo, ClipDisplayItem, ClipId, ColorF, ComplexClipRegion, DisplayItem}; use {ExtendMode, FilterOp, FontKey, GlyphInstance, GlyphOptions, Gradient, GradientDisplayItem}; use {GradientStop, IframeDisplayItem, ImageDisplayItem, ImageKey, ImageMask, ImageRendering}; -use {LayoutPoint, LayoutRect, LayoutSize, LayoutTransform, LayoutVector2D, MixBlendMode}; -use {PipelineId, PropertyBinding, PushStackingContextDisplayItem, RadialGradient}; +use {LayoutPoint, LayoutRect, LayoutSize, LayoutTransform, LayoutVector2D, LocalClip}; +use {MixBlendMode, PipelineId, PropertyBinding, PushStackingContextDisplayItem, RadialGradient}; use {RadialGradientDisplayItem, RectangleDisplayItem, ScrollPolicy, SpecificDisplayItem}; use {StackingContext, TextDisplayItem, TransformStyle, WebGLContextId, WebGLDisplayItem}; use {YuvColorSpace, YuvData, YuvImageDisplayItem}; @@ -137,7 +137,7 @@ impl<'a> BuiltDisplayListIter<'a> { cur_item: DisplayItem { // Dummy data, will be overwritten by `next` item: SpecificDisplayItem::PopStackingContext, rect: LayoutRect::zero(), - clip_rect: LayoutRect::zero(), + local_clip: LocalClip::from(LayoutRect::zero()), clip_and_scroll: ClipAndScrollInfo::simple(ClipId::new(0, PipelineId(0, 0))), }, cur_stops: ItemRange::default(), @@ -272,8 +272,8 @@ impl<'a, 'b> DisplayItemRef<'a, 'b> { self.iter.cur_item.rect } - pub fn clip_rect(&self) -> &LayoutRect { - &self.iter.cur_item.clip_rect + pub fn local_clip(&self) -> &LocalClip { + &self.iter.cur_item.local_clip } pub fn clip_and_scroll(&self) -> ClipAndScrollInfo { @@ -446,11 +446,15 @@ impl DisplayListBuilder { self.data = temp.data; } - fn push_item(&mut self, item: SpecificDisplayItem, rect: LayoutRect, clip_rect: LayoutRect) { + fn push_item(&mut self, + item: SpecificDisplayItem, + rect: LayoutRect, + local_clip: Option) { + let local_clip = local_clip.unwrap_or_else(|| LocalClip::from(rect)); bincode::serialize_into(&mut self.data, &DisplayItem { item, rect, - clip_rect, + local_clip: local_clip, clip_and_scroll: *self.clip_stack.last().unwrap(), }, bincode::Infinite).unwrap(); } @@ -459,7 +463,7 @@ impl DisplayListBuilder { bincode::serialize_into(&mut self.data, &DisplayItem { item, rect: LayoutRect::zero(), - clip_rect: LayoutRect::zero(), + local_clip: LocalClip::from(LayoutRect::zero()), clip_and_scroll: *self.clip_stack.last().unwrap(), }, bincode::Infinite).unwrap(); } @@ -482,17 +486,17 @@ impl DisplayListBuilder { debug_assert_eq!(len, count); } - pub fn push_rect(&mut self, rect: LayoutRect, clip_rect: LayoutRect, color: ColorF) { + pub fn push_rect(&mut self, rect: LayoutRect, local_clip: Option, color: ColorF) { let item = SpecificDisplayItem::Rectangle(RectangleDisplayItem { color, }); - self.push_item(item, rect, clip_rect); + self.push_item(item, rect, local_clip); } pub fn push_image(&mut self, rect: LayoutRect, - clip_rect: LayoutRect, + local_clip: Option, stretch_size: LayoutSize, tile_spacing: LayoutSize, image_rendering: ImageRendering, @@ -504,13 +508,13 @@ impl DisplayListBuilder { image_rendering, }); - self.push_item(item, rect, clip_rect); + self.push_item(item, rect, local_clip); } /// Push a yuv image. All planar data in yuv image should use the same buffer type. pub fn push_yuv_image(&mut self, rect: LayoutRect, - clip_rect: LayoutRect, + local_clip: Option, yuv_data: YuvData, color_space: YuvColorSpace, image_rendering: ImageRendering) { @@ -519,22 +523,22 @@ impl DisplayListBuilder { color_space, image_rendering, }); - self.push_item(item, rect, clip_rect); + self.push_item(item, rect, local_clip); } pub fn push_webgl_canvas(&mut self, rect: LayoutRect, - clip_rect: LayoutRect, + local_clip: Option, context_id: WebGLContextId) { let item = SpecificDisplayItem::WebGL(WebGLDisplayItem { context_id, }); - self.push_item(item, rect, clip_rect); + self.push_item(item, rect, local_clip); } pub fn push_text(&mut self, rect: LayoutRect, - clip_rect: LayoutRect, + local_clip: Option, glyphs: &[GlyphInstance], font_key: FontKey, color: ColorF, @@ -556,7 +560,7 @@ impl DisplayListBuilder { glyph_options, }); - self.push_item(item, rect, clip_rect); + self.push_item(item, rect, local_clip); self.push_iter(glyphs); } } @@ -734,7 +738,7 @@ impl DisplayListBuilder { pub fn push_border(&mut self, rect: LayoutRect, - clip_rect: LayoutRect, + local_clip: Option, widths: BorderWidths, details: BorderDetails) { let item = SpecificDisplayItem::Border(BorderDisplayItem { @@ -742,12 +746,12 @@ impl DisplayListBuilder { widths, }); - self.push_item(item, rect, clip_rect); + self.push_item(item, rect, local_clip); } pub fn push_box_shadow(&mut self, rect: LayoutRect, - clip_rect: LayoutRect, + local_clip: Option, box_bounds: LayoutRect, offset: LayoutVector2D, color: ColorF, @@ -765,12 +769,12 @@ impl DisplayListBuilder { clip_mode, }); - self.push_item(item, rect, clip_rect); + self.push_item(item, rect, local_clip); } pub fn push_gradient(&mut self, rect: LayoutRect, - clip_rect: LayoutRect, + local_clip: Option, gradient: Gradient, tile_size: LayoutSize, tile_spacing: LayoutSize) { @@ -780,12 +784,12 @@ impl DisplayListBuilder { tile_spacing, }); - self.push_item(item, rect, clip_rect); + self.push_item(item, rect, local_clip); } pub fn push_radial_gradient(&mut self, rect: LayoutRect, - clip_rect: LayoutRect, + local_clip: Option, gradient: RadialGradient, tile_size: LayoutSize, tile_spacing: LayoutSize) { @@ -795,7 +799,7 @@ impl DisplayListBuilder { tile_spacing, }); - self.push_item(item, rect, clip_rect); + self.push_item(item, rect, local_clip); } pub fn push_stacking_context(&mut self, @@ -816,7 +820,7 @@ impl DisplayListBuilder { } }); - self.push_item(item, bounds, bounds); + self.push_item(item, bounds, None); self.push_iter(&filters); } @@ -855,7 +859,7 @@ impl DisplayListBuilder { image_mask: image_mask, }); - self.push_item(item, content_rect, clip_rect); + self.push_item(item, content_rect, Some(LocalClip::from(clip_rect))); self.push_iter(complex_clips); id } @@ -875,7 +879,7 @@ impl DisplayListBuilder { image_mask: image_mask, }); - self.push_item(item, clip_rect, clip_rect); + self.push_item(item, clip_rect, Some(LocalClip::from(clip_rect))); self.push_iter(complex_clips); id } @@ -895,7 +899,7 @@ impl DisplayListBuilder { pub fn push_iframe(&mut self, rect: LayoutRect, pipeline_id: PipelineId) { let item = SpecificDisplayItem::Iframe(IframeDisplayItem { pipeline_id: pipeline_id }); - self.push_item(item, rect, rect); + self.push_item(item, rect, None); } // Don't use this function. It will go away. diff --git a/wrench/src/yaml_frame_reader.rs b/wrench/src/yaml_frame_reader.rs index 7c2407ac43..8b2ff69c47 100644 --- a/wrench/src/yaml_frame_reader.rs +++ b/wrench/src/yaml_frame_reader.rs @@ -213,34 +213,34 @@ impl YamlFrameReader { } } - fn handle_rect(&mut self, item: &Yaml, clip_rect: LayoutRect) { + fn handle_rect(&mut self, item: &Yaml, local_clip: LocalClip) { let bounds_key = if item["type"].is_badvalue() { "rect" } else { "bounds" }; let rect = item[bounds_key].as_rect().expect("rect type must have bounds"); let color = item["color"].as_colorf().unwrap_or(*WHITE_COLOR); - self.builder().push_rect(rect, clip_rect, color); + self.builder().push_rect(rect, Some(local_clip), color); } - fn handle_gradient(&mut self, item: &Yaml, clip_rect: LayoutRect) { + fn handle_gradient(&mut self, item: &Yaml, local_clip: LocalClip) { let bounds_key = if item["type"].is_badvalue() { "gradient" } else { "bounds" }; let bounds = item[bounds_key].as_rect().expect("gradient must have bounds"); let gradient = self.to_gradient(item); let tile_size = item["tile-size"].as_size().unwrap_or(bounds.size); let tile_spacing = item["tile-spacing"].as_size().unwrap_or(LayoutSize::zero()); - self.builder().push_gradient(bounds, clip_rect, gradient, tile_size, tile_spacing); + self.builder().push_gradient(bounds, Some(local_clip), gradient, tile_size, tile_spacing); } - fn handle_radial_gradient(&mut self, item: &Yaml, clip_rect: LayoutRect) { + fn handle_radial_gradient(&mut self, item: &Yaml, local_clip: LocalClip) { let bounds_key = if item["type"].is_badvalue() { "radial-gradient" } else { "bounds" }; let bounds = item[bounds_key].as_rect().expect("radial gradient must have bounds"); let gradient = self.to_radial_gradient(item); let tile_size = item["tile-size"].as_size().unwrap_or(bounds.size); let tile_spacing = item["tile-spacing"].as_size().unwrap_or(LayoutSize::zero()); - self.builder().push_radial_gradient(bounds, clip_rect, gradient, tile_size, tile_spacing); + self.builder().push_radial_gradient(bounds, Some(local_clip), gradient, tile_size, tile_spacing); } - fn handle_border(&mut self, wrench: &mut Wrench, item: &Yaml, clip_rect: LayoutRect) { + fn handle_border(&mut self, wrench: &mut Wrench, item: &Yaml, local_clip: LocalClip) { let bounds_key = if item["type"].is_badvalue() { "border" } else { "bounds" }; let bounds = item[bounds_key].as_rect().expect("borders must have bounds"); let widths = item["width"].as_vec_f32().expect("borders must have width(s)"); @@ -350,11 +350,11 @@ impl YamlFrameReader { None }; if let Some(details) = border_details { - self.builder().push_border(bounds, clip_rect, widths, details); + self.builder().push_border(bounds, Some(local_clip), widths, details); } } - fn handle_box_shadow(&mut self, item: &Yaml, clip_rect: LayoutRect) { + fn handle_box_shadow(&mut self, item: &Yaml, local_clip: LocalClip) { let bounds_key = if item["type"].is_badvalue() { "box-shadow" } else { "bounds" }; let bounds = item[bounds_key].as_rect().expect("box shadow must have bounds"); let box_bounds = item["box-bounds"].as_rect().unwrap_or(bounds); @@ -375,7 +375,7 @@ impl YamlFrameReader { }; self.builder().push_box_shadow(bounds, - clip_rect, + Some(local_clip), box_bounds, offset, color, @@ -392,7 +392,7 @@ impl YamlFrameReader { file } - fn handle_image(&mut self, wrench: &mut Wrench, item: &Yaml, clip_rect: LayoutRect) { + fn handle_image(&mut self, wrench: &mut Wrench, item: &Yaml, local_clip: LocalClip) { let filename = &item[if item["type"].is_badvalue() { "image" } else { "src" }]; let tiling = item["tile-size"].as_i64(); let (image_key, image_dims) = wrench.add_or_get_image(&self.rsrc_path(filename), tiling); @@ -419,14 +419,14 @@ impl YamlFrameReader { Some(_) => panic!("ImageRendering can be auto, crisp-edges, or pixelated -- got {:?}", item), }; self.builder().push_image(bounds, - clip_rect, + Some(local_clip), stretch_size, tile_spacing, rendering, image_key); } - fn handle_text(&mut self, wrench: &mut Wrench, item: &Yaml, clip_rect: LayoutRect) { + fn handle_text(&mut self, wrench: &mut Wrench, item: &Yaml, local_clip: LocalClip) { let size = item["size"].as_pt_to_au().unwrap_or(Au::from_f32_px(16.0)); let color = item["color"].as_colorf().unwrap_or(*BLACK_COLOR); let blur_radius = item["blur-radius"].as_force_f32().unwrap_or(0.0); @@ -493,7 +493,7 @@ impl YamlFrameReader { }; self.builder().push_text(rect, - clip_rect, + Some(local_clip), &glyphs, font_key, color, @@ -508,8 +508,18 @@ impl YamlFrameReader { self.builder().push_iframe(bounds, pipeline_id); } + pub fn get_local_clip_for_item(&mut self, yaml: &Yaml, full_clip: LayoutRect) -> LocalClip { + let rect = yaml["clip-rect"].as_rect().unwrap_or(full_clip); + let complex_clip = &yaml["complex-clip"]; + if !complex_clip.is_badvalue() { + LocalClip::RoundedRect(rect, self.to_complex_clip_region(complex_clip)) + } else { + LocalClip::from(rect) + } + } + pub fn add_display_list_items_from_yaml(&mut self, wrench: &mut Wrench, yaml: &Yaml) { - let full_clip_rect = LayoutRect::new(LayoutPoint::zero(), wrench.window_size_f32()); + let full_clip = LayoutRect::new(LayoutPoint::zero(), wrench.window_size_f32()); for item in yaml.as_vec().unwrap() { // an explicit type can be skipped with some shorthand @@ -548,18 +558,17 @@ impl YamlFrameReader { self.builder().push_clip_and_scroll_info(clip_scroll_info); } - let clip_rect = item["clip-rect"].as_rect().unwrap_or(full_clip_rect); - + let local_clip = self.get_local_clip_for_item(item, full_clip); match item_type { - "rect" => self.handle_rect(item, clip_rect), - "image" => self.handle_image(wrench, item, clip_rect), - "text" | "glyphs" => self.handle_text(wrench, item, clip_rect), + "rect" => self.handle_rect(item, local_clip), + "image" => self.handle_image(wrench, item, local_clip), + "text" | "glyphs" => self.handle_text(wrench, item, local_clip), "scroll-frame" => self.handle_scroll_frame(wrench, item), "clip" => self.handle_clip(wrench, item), - "border" => self.handle_border(wrench, item, clip_rect), - "gradient" => self.handle_gradient(item, clip_rect), - "radial-gradient" => self.handle_radial_gradient(item, clip_rect), - "box-shadow" => self.handle_box_shadow(item, clip_rect), + "border" => self.handle_border(wrench, item, local_clip), + "gradient" => self.handle_gradient(item, local_clip), + "radial-gradient" => self.handle_radial_gradient(item, local_clip), + "box-shadow" => self.handle_box_shadow(item, local_clip), "iframe" => self.handle_iframe(item), "stacking-context" => self.add_stacking_context_from_yaml(wrench, item, false), _ => println!("Skipping unknown item type: {:?}", item), diff --git a/wrench/src/yaml_frame_writer.rs b/wrench/src/yaml_frame_writer.rs index 2c983ec003..7b2f1f9656 100644 --- a/wrench/src/yaml_frame_writer.rs +++ b/wrench/src/yaml_frame_writer.rs @@ -432,7 +432,14 @@ impl YamlFrameWriter { Some(path) } - fn make_clip_complex_node(&mut self, + fn make_complex_clip_node(&mut self, complex_clip: &ComplexClipRegion) -> Yaml { + let mut t = new_table(); + rect_node(&mut t, "rect", &complex_clip.rect); + yaml_node(&mut t, "radius", maybe_radius_yaml(&complex_clip.radii).unwrap()); + Yaml::Hash(t) + } + + fn make_complex_clips_node(&mut self, complex_clip_count: usize, complex_clips: ItemRange, list: &BuiltDisplayList) @@ -445,10 +452,7 @@ impl YamlFrameWriter { if ccx.radii.is_zero() { rect_yaml(&ccx.rect) } else { - let mut t = new_table(); - rect_node(&mut t, "rect", &ccx.rect); - yaml_node(&mut t, "radius", maybe_radius_yaml(&ccx.radii).unwrap()); - Yaml::Hash(t) + self.make_complex_clip_node(&ccx) } ).collect(); Some(Yaml::Array(complex_items)) @@ -487,7 +491,11 @@ impl YamlFrameWriter { let mut v = new_table(); rect_node(&mut v, "bounds", &base.rect()); - rect_node(&mut v, "clip-rect", &base.clip_rect()); + + rect_node(&mut v, "clip-rect", base.local_clip().clip_rect()); + if let &LocalClip::RoundedRect(_, ref region) = base.local_clip() { + yaml_node(&mut v, "complex-clip", self.make_complex_clip_node(region)); + } let clip_and_scroll_info = clip_id_mapper.fix_ids_for_nesting(&base.clip_and_scroll()); let clip_and_scroll_yaml = match clip_id_mapper.map_info(&clip_and_scroll_info) { @@ -750,9 +758,9 @@ impl YamlFrameWriter { size_node(&mut v, "content-size", &base.rect().size); let &(complex_clips, complex_clip_count) = base.complex_clip(); - if let Some(complex) = self.make_clip_complex_node(complex_clip_count, - complex_clips, - display_list) { + if let Some(complex) = self.make_complex_clips_node(complex_clip_count, + complex_clips, + display_list) { yaml_node(&mut v, "complex", complex); } @@ -764,12 +772,12 @@ impl YamlFrameWriter { str_node(&mut v, "type", "scroll-frame"); usize_node(&mut v, "id", clip_id_mapper.add_id(item.id)); size_node(&mut v, "content-size", &base.rect().size); - rect_node(&mut v, "bounds", &base.clip_rect()); + rect_node(&mut v, "bounds", &base.local_clip().clip_rect()); let &(complex_clips, complex_clip_count) = base.complex_clip(); - if let Some(complex) = self.make_clip_complex_node(complex_clip_count, - complex_clips, - display_list) { + if let Some(complex) = self.make_complex_clips_node(complex_clip_count, + complex_clips, + display_list) { yaml_node(&mut v, "complex", complex); } From 957ded1d4b886470f353b322982ccc839214b99d Mon Sep 17 00:00:00 2001 From: Martin Robinson Date: Sat, 24 Jun 2017 12:09:59 +0200 Subject: [PATCH 4/4] Update the WebRender version This is necessary because of the changes to the API. --- Cargo.lock | 8 ++++---- webrender/Cargo.toml | 2 +- webrender_api/Cargo.toml | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 536e77a8dc..515fc90573 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -21,7 +21,7 @@ dependencies = [ "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "servo-glutin 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", - "webrender 0.46.0", + "webrender 0.47.0", "yaml-rust 0.3.4 (git+https://github.com/vvuk/yaml-rust)", ] @@ -1022,7 +1022,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "webrender" -version = "0.46.0" +version = "0.47.0" dependencies = [ "angle 0.1.2 (git+https://github.com/servo/angle?branch=servo)", "app_units 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1048,12 +1048,12 @@ dependencies = [ "servo-glutin 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)", "thread_profiler 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", - "webrender_api 0.46.0", + "webrender_api 0.47.0", ] [[package]] name = "webrender_api" -version = "0.46.0" +version = "0.47.0" dependencies = [ "app_units 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "bincode 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/webrender/Cargo.toml b/webrender/Cargo.toml index 80e32bc65e..9b0d00e0dd 100644 --- a/webrender/Cargo.toml +++ b/webrender/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "webrender" -version = "0.46.0" +version = "0.47.0" authors = ["Glenn Watson "] license = "MPL-2.0" repository = "https://github.com/servo/webrender" diff --git a/webrender_api/Cargo.toml b/webrender_api/Cargo.toml index 23c9c1aac4..308bcd2d8b 100644 --- a/webrender_api/Cargo.toml +++ b/webrender_api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "webrender_api" -version = "0.46.0" +version = "0.47.0" authors = ["Glenn Watson "] license = "MPL-2.0" repository = "https://github.com/servo/webrender"