Bug 1393383 - Update WebRender draft
authorChih-Yi Leu <subsevenx2001@gmail.com>
Thu, 19 Oct 2017 12:15:38 +0800
changeset 683254 2d5f8b86fdbf35fc47b924ed9ce6779aae46d240
parent 683249 31af3ee0436093bfd3300e9002f1118df0420309
child 683255 a081d6767e9419546059d9f8edab6d8293376dc7
push id85310
push userbmo:cleu@mozilla.com
push dateThu, 19 Oct 2017 13:19:00 +0000
bugs1393383
milestone58.0a1
Bug 1393383 - Update WebRender MozReview-Commit-ID: 7VKXaMrQfEY
gfx/webrender/examples/basic.rs
gfx/webrender/res/brush_mask.glsl
gfx/webrender/src/frame_builder.rs
gfx/webrender/src/prim_store.rs
gfx/webrender_api/src/display_item.rs
gfx/webrender_api/src/display_list.rs
--- a/gfx/webrender/examples/basic.rs
+++ b/gfx/webrender/examples/basic.rs
@@ -334,17 +334,17 @@ impl Example for App {
 
             builder.push_box_shadow(
                 &info,
                 simple_box_bounds,
                 offset,
                 color,
                 blur_radius,
                 spread_radius,
-                simple_border_radius,
+                BorderRadius::uniform(simple_border_radius),
                 box_shadow_type,
             );
         }
 
         builder.pop_stacking_context();
     }
 
     fn on_event(&mut self, event: glutin::Event, api: &RenderApi, document_id: DocumentId) -> bool {
--- a/gfx/webrender/res/brush_mask.glsl
+++ b/gfx/webrender/res/brush_mask.glsl
@@ -9,36 +9,38 @@ flat varying vec4 vClipCenter_Radius_TL;
 flat varying vec4 vClipCenter_Radius_TR;
 flat varying vec4 vClipCenter_Radius_BR;
 flat varying vec4 vClipCenter_Radius_BL;
 
 #ifdef WR_VERTEX_SHADER
 
 struct BrushPrimitive {
     float clip_mode;
-    float radius;
+    vec2 radius_tl;
+    vec2 radius_tr;
+    vec2 radius_br;
+    vec2 radius_bl;
 };
 
 BrushPrimitive fetch_brush_primitive(int address) {
-    vec4 data = fetch_from_resource_cache_1(address);
-    return BrushPrimitive(data.x, data.y);
+    vec4 data[3] = fetch_from_resource_cache_3(address);
+    return BrushPrimitive(data[0].x, data[1].xy, data[1].zw, data[2].xy, data[2].zw);
 }
 
 void brush_vs(int prim_address, vec4 prim_rect) {
     // Load the specific primitive.
     BrushPrimitive prim = fetch_brush_primitive(prim_address + 2);
 
     // Write clip parameters
     vClipMode = prim.clip_mode;
 
-    vec2 r = vec2(prim.radius);
-    vClipCenter_Radius_TL = vec4(prim_rect.xy + vec2(r.x, r.y), r);
-    vClipCenter_Radius_TR = vec4(prim_rect.zy + vec2(-r.x, r.y), r);
-    vClipCenter_Radius_BR = vec4(prim_rect.zw + vec2(-r.x, -r.y), r);
-    vClipCenter_Radius_BL = vec4(prim_rect.xw + vec2(r.x, -r.y), r);
+    vClipCenter_Radius_TL = vec4(prim_rect.xy + prim.radius_tl, prim.radius_tl);
+    vClipCenter_Radius_TR = vec4(prim_rect.zy + vec2(-prim.radius_tr.x, prim.radius_tr.y), prim.radius_tr);
+    vClipCenter_Radius_BR = vec4(prim_rect.zw - prim.radius_br, prim.radius_br);
+    vClipCenter_Radius_BL = vec4(prim_rect.xw + vec2(prim.radius_bl.x, -prim.radius_bl.y), prim.radius_bl);
 }
 #endif
 
 #ifdef WR_FRAGMENT_SHADER
 vec4 brush_fs(vec2 local_pos, vec4 local_rect) {
     // TODO(gw): The mask code below is super-inefficient. Once we
     // start using primitive segments in brush shaders, this can
     // be made much faster.
--- a/gfx/webrender/src/frame_builder.rs
+++ b/gfx/webrender/src/frame_builder.rs
@@ -1,14 +1,14 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * 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, BorderRadius, BoxShadowClipMode, BuiltDisplayList};
-use api::{ComplexClipRegion, ClipAndScrollInfo, ClipId, ColorF};
+use api::{ComplexClipRegion, ClipAndScrollInfo, ClipId, ColorF, LayoutSize};
 use api::{DeviceIntPoint, DeviceIntRect, DeviceIntSize, DeviceUintRect, DeviceUintSize};
 use api::{ExtendMode, FilterOp, FontInstance, FontRenderMode};
 use api::{GlyphInstance, GlyphOptions, GradientStop, HitTestFlags, HitTestItem, HitTestResult};
 use api::{ImageKey, ImageRendering, ItemRange, ItemTag, LayerPoint, LayerPrimitiveInfo, LayerRect};
 use api::{LayerPixel, LayerSize, LayerToScrollTransform, LayerVector2D, LayoutVector2D, LineOrientation};
 use api::{LineStyle, LocalClip, PipelineId, RepeatMode};
 use api::{ScrollSensitivity, Shadow, TileOffset, TransformStyle};
 use api::{WorldPixel, WorldPoint, YuvColorSpace, YuvData, device_length};
@@ -1253,77 +1253,73 @@ impl FrameBuilder {
     pub fn add_box_shadow(
         &mut self,
         clip_and_scroll: ClipAndScrollInfo,
         prim_info: &LayerPrimitiveInfo,
         box_offset: &LayerVector2D,
         color: &ColorF,
         blur_radius: f32,
         spread_radius: f32,
-        border_radius: f32,
+        border_radius: BorderRadius,
         clip_mode: BoxShadowClipMode,
     ) {
         if color.a == 0.0 {
             return;
         }
 
         let spread_amount = match clip_mode {
             BoxShadowClipMode::Outset => {
                 spread_radius
             }
             BoxShadowClipMode::Inset => {
                 -spread_radius
             }
         };
 
-        // Adjust the shadow box radius as per:
-        // https://drafts.csswg.org/css-backgrounds-3/#shadow-shape
-        let sharpness_scale = if border_radius < spread_radius {
-            let r = border_radius / spread_amount;
-            1.0 + (r - 1.0) * (r - 1.0) * (r - 1.0)
-        } else {
-            1.0
-        };
-        let shadow_radius = (border_radius + spread_amount * sharpness_scale).max(0.0);
+        let shadow_radius = adjust_border_radius_for_box_shadow(
+            border_radius,
+            spread_amount,
+            spread_radius
+        );
         let shadow_rect = prim_info.rect
                                    .translate(box_offset)
                                    .inflate(spread_amount, spread_amount);
 
         if blur_radius == 0.0 {
             let mut clips = Vec::new();
 
             let fast_info = match clip_mode {
                 BoxShadowClipMode::Outset => {
                     // TODO(gw): Add a fast path for ClipOut + zero border radius!
                     clips.push(ClipSource::RoundedRectangle(
                         prim_info.rect,
-                        BorderRadius::uniform(border_radius),
+                        border_radius,
                         ClipMode::ClipOut
                     ));
 
                     LayerPrimitiveInfo::with_clip(
                         shadow_rect,
                         LocalClip::RoundedRect(
                             shadow_rect,
-                            ComplexClipRegion::new(shadow_rect, BorderRadius::uniform(shadow_radius)),
+                            ComplexClipRegion::new(shadow_rect, shadow_radius),
                         ),
                     )
                 }
                 BoxShadowClipMode::Inset => {
                     clips.push(ClipSource::RoundedRectangle(
                         shadow_rect,
-                        BorderRadius::uniform(shadow_radius),
+                        shadow_radius,
                         ClipMode::ClipOut
                     ));
 
                     LayerPrimitiveInfo::with_clip(
                         prim_info.rect,
                         LocalClip::RoundedRect(
                             prim_info.rect,
-                            ComplexClipRegion::new(prim_info.rect, BorderRadius::uniform(border_radius)),
+                            ComplexClipRegion::new(prim_info.rect, border_radius),
                         ),
                     )
                 }
             };
 
             self.add_primitive(
                 clip_and_scroll,
                 &fast_info,
@@ -1361,17 +1357,17 @@ impl FrameBuilder {
                         Vec::new(),
                         PrimitiveContainer::Brush(brush_prim),
                     );
 
                     pic_prim.add_primitive(brush_prim_index, clip_and_scroll);
 
                     extra_clips.push(ClipSource::RoundedRectangle(
                         prim_info.rect,
-                        BorderRadius::uniform(border_radius),
+                        border_radius,
                         ClipMode::ClipOut,
                     ));
 
                     let pic_rect = shadow_rect.inflate(blur_offset, blur_offset);
                     LayerPrimitiveInfo::new(pic_rect)
                 }
                 BoxShadowClipMode::Inset => {
                     let brush_prim = BrushPrimitive {
@@ -1391,17 +1387,17 @@ impl FrameBuilder {
                         Vec::new(),
                         PrimitiveContainer::Brush(brush_prim),
                     );
 
                     pic_prim.add_primitive(brush_prim_index, clip_and_scroll);
 
                     extra_clips.push(ClipSource::RoundedRectangle(
                         prim_info.rect,
-                        BorderRadius::uniform(border_radius),
+                        border_radius,
                         ClipMode::Clip,
                     ));
 
                     let pic_rect = prim_info.rect.inflate(blur_offset, blur_offset);
                     LayerPrimitiveInfo::with_clip_rect(pic_rect, prim_info.rect)
                 }
             };
 
@@ -2321,8 +2317,72 @@ impl FrameBuilder {
             passes,
             layer_texture_data: self.packed_layers.clone(),
             render_tasks,
             deferred_resolves,
             gpu_cache_updates: Some(gpu_cache_updates),
         }
     }
 }
+
+fn adjust_border_radius_for_box_shadow(
+    radius: BorderRadius,
+    spread_amount: f32,
+    spread_radius: f32,
+) -> BorderRadius {
+    BorderRadius {
+        top_left: adjust_corner_for_box_shadow(
+            radius.top_left,
+            spread_radius,
+            spread_amount,
+        ),
+        top_right: adjust_corner_for_box_shadow(
+            radius.top_right,
+            spread_radius,
+            spread_amount,
+        ),
+        bottom_right: adjust_corner_for_box_shadow(
+            radius.bottom_right,
+            spread_radius,
+            spread_amount,
+        ),
+        bottom_left: adjust_corner_for_box_shadow(
+            radius.bottom_left,
+            spread_radius,
+            spread_amount,
+        ),
+    }
+}
+
+fn adjust_corner_for_box_shadow(
+    corner: LayoutSize,
+    spread_amount: f32,
+    spread_radius: f32,
+) -> LayoutSize {
+    LayoutSize::new(
+        adjust_radius_for_box_shadow(
+            corner.width,
+            spread_radius,
+            spread_amount
+        ),
+        adjust_radius_for_box_shadow(
+            corner.height,
+            spread_radius,
+            spread_amount
+        ),
+    )
+}
+
+fn adjust_radius_for_box_shadow(
+    border_radius: f32,
+    spread_amount: f32,
+    spread_radius: f32,
+) -> f32 {
+    // Adjust the shadow box radius as per:
+    // https://drafts.csswg.org/css-backgrounds-3/#shadow-shape
+    let sharpness_scale = if border_radius < spread_radius {
+        let r = border_radius / spread_amount;
+        1.0 + (r - 1.0) * (r - 1.0) * (r - 1.0)
+    } else {
+        1.0
+    };
+    (border_radius + spread_amount * sharpness_scale).max(0.0)
+}
--- a/gfx/webrender/src/prim_store.rs
+++ b/gfx/webrender/src/prim_store.rs
@@ -162,27 +162,39 @@ impl ToGpuBlocks for RectanglePrimitive 
     fn write_gpu_blocks(&self, mut request: GpuDataRequest) {
         request.push(self.color);
     }
 }
 
 #[derive(Debug)]
 pub struct BrushPrimitive {
     pub clip_mode: ClipMode,
-    pub radius: f32,
+    pub radius: BorderRadius,
 }
 
 impl ToGpuBlocks for BrushPrimitive {
     fn write_gpu_blocks(&self, mut request: GpuDataRequest) {
         request.push([
             self.clip_mode as u32 as f32,
-            self.radius,
+            0.0,
             0.0,
             0.0
         ]);
+        request.push([
+            self.radius.top_left.width,
+            self.radius.top_left.height,
+            self.radius.top_right.width,
+            self.radius.top_right.height,
+        ]);
+        request.push([
+            self.radius.bottom_right.width,
+            self.radius.bottom_right.height,
+            self.radius.bottom_left.width,
+            self.radius.bottom_left.height,
+        ]);
     }
 }
 
 #[derive(Debug, Clone)]
 #[repr(C)]
 pub struct LinePrimitive {
     pub color: ColorF,
     pub style: LineStyle,
--- a/gfx/webrender_api/src/display_item.rs
+++ b/gfx/webrender_api/src/display_item.rs
@@ -292,17 +292,17 @@ pub enum BoxShadowClipMode {
 
 #[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
 pub struct BoxShadowDisplayItem {
     pub box_bounds: LayoutRect,
     pub offset: LayoutVector2D,
     pub color: ColorF,
     pub blur_radius: f32,
     pub spread_radius: f32,
-    pub border_radius: f32,
+    pub border_radius: BorderRadius,
     pub clip_mode: BoxShadowClipMode,
 }
 
 #[repr(C)]
 #[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
 pub struct Shadow {
     pub offset: LayoutVector2D,
     pub color: ColorF,
--- a/gfx/webrender_api/src/display_list.rs
+++ b/gfx/webrender_api/src/display_list.rs
@@ -7,17 +7,17 @@ use {ClipAndScrollInfo, ClipDisplayItem,
 use {ExtendMode, FilterOp, FontInstanceKey, GlyphInstance};
 use {GlyphOptions, Gradient, GradientDisplayItem, GradientStop, IframeDisplayItem};
 use {ImageDisplayItem, ImageKey, ImageMask, ImageRendering, LayerPrimitiveInfo, LayoutPoint};
 use {LayoutPrimitiveInfo, LayoutRect, LayoutSize, LayoutTransform, LayoutVector2D};
 use {LineDisplayItem, LineOrientation, LineStyle, LocalClip, MixBlendMode, PipelineId};
 use {PropertyBinding, PushStackingContextDisplayItem, RadialGradient, RadialGradientDisplayItem};
 use {RectangleDisplayItem, ScrollFrameDisplayItem, ScrollPolicy, ScrollSensitivity};
 use {SpecificDisplayItem, StackingContext, StickyFrameDisplayItem, StickyFrameInfo};
-use {TextDisplayItem, Shadow, TransformStyle, YuvColorSpace, YuvData};
+use {BorderRadius, TextDisplayItem, Shadow, TransformStyle, YuvColorSpace, YuvData};
 use YuvImageDisplayItem;
 use bincode;
 use serde::{Deserialize, Serialize, Serializer};
 use serde::ser::{SerializeMap, SerializeSeq};
 use std::io::{Read, Write};
 use std::{io, ptr};
 use std::marker::PhantomData;
 use std::slice;
@@ -1019,17 +1019,17 @@ impl DisplayListBuilder {
     pub fn push_box_shadow(
         &mut self,
         info: &LayoutPrimitiveInfo,
         box_bounds: LayoutRect,
         offset: LayoutVector2D,
         color: ColorF,
         blur_radius: f32,
         spread_radius: f32,
-        border_radius: f32,
+        border_radius: BorderRadius,
         clip_mode: BoxShadowClipMode,
     ) {
         let item = SpecificDisplayItem::BoxShadow(BoxShadowDisplayItem {
             box_bounds,
             offset,
             color,
             blur_radius,
             spread_radius,