Bug 1415034 - Add drop-shadow support. r=kats draft
authorMorris Tseng <mtseng@mozilla.com>
Fri, 24 Nov 2017 15:05:23 +0800
changeset 710881 43738ae9dd2d185d2758d553f26c65dd82a5758d
parent 710859 a16f868d488b41c6871c705b0a15c1b5b3deb4ce
child 743678 e633fda87b0399bf8f875673997026d75d4ecea6
push id92928
push userbmo:mtseng@mozilla.com
push dateTue, 12 Dec 2017 16:15:37 +0000
reviewerskats
bugs1415034
milestone59.0a1
Bug 1415034 - Add drop-shadow support. r=kats The long-chain.html failure is tracking by https://github.com/servo/webrender/issues/2197 MozReview-Commit-ID: FECidSvTQrY
gfx/webrender_bindings/WebRenderTypes.h
gfx/webrender_bindings/src/bindings.rs
gfx/webrender_bindings/webrender_ffi_generated.h
layout/painting/nsDisplayList.cpp
layout/reftests/svg/filters/css-filter-chains/reftest.list
layout/reftests/svg/filters/css-filters/reftest.list
--- a/gfx/webrender_bindings/WebRenderTypes.h
+++ b/gfx/webrender_bindings/WebRenderTypes.h
@@ -725,16 +725,18 @@ static inline wr::WrFilterOpType ToWrFil
     case NS_STYLE_FILTER_INVERT:
       return wr::WrFilterOpType::Invert;
     case NS_STYLE_FILTER_OPACITY:
       return wr::WrFilterOpType::Opacity;
     case NS_STYLE_FILTER_SATURATE:
       return wr::WrFilterOpType::Saturate;
     case NS_STYLE_FILTER_SEPIA:
       return wr::WrFilterOpType::Sepia;
+    case NS_STYLE_FILTER_DROP_SHADOW:
+      return wr::WrFilterOpType::DropShadow;
   }
   MOZ_ASSERT_UNREACHABLE("Tried to convert unknown filter type.");
   return wr::WrFilterOpType::Grayscale;
 }
 
 // Corresponds to an "internal" webrender clip id. That is, a
 // ClipId::Clip(x,pipeline_id) maps to a WrClipId{x}. We use a struct wrapper
 // instead of a typedef so that this is a distinct type from FrameMetrics::ViewID
--- a/gfx/webrender_bindings/src/bindings.rs
+++ b/gfx/webrender_bindings/src/bindings.rs
@@ -354,23 +354,26 @@ pub enum WrFilterOpType {
   Brightness = 1,
   Contrast = 2,
   Grayscale = 3,
   HueRotate = 4,
   Invert = 5,
   Opacity = 6,
   Saturate = 7,
   Sepia = 8,
+  DropShadow = 9,
 }
 
 #[repr(C)]
 #[derive(Copy, Clone)]
 pub struct WrFilterOp {
     filter_type: WrFilterOpType,
-    argument: c_float,
+    argument: c_float, // holds radius for DropShadow; value for other filters
+    offset: LayoutVector2D, // only used for DropShadow
+    color: ColorF, // only used for DropShadow
 }
 
 /// cbindgen:derive-eq=false
 #[repr(C)]
 #[derive(Debug)]
 pub struct WrTransformProperty {
     pub id: u64,
     pub transform: LayoutTransform,
@@ -1288,16 +1291,19 @@ pub extern "C" fn wr_dp_push_stacking_co
             WrFilterOpType::Brightness => FilterOp::Brightness(c_filter.argument),
             WrFilterOpType::Contrast => FilterOp::Contrast(c_filter.argument),
             WrFilterOpType::Grayscale => FilterOp::Grayscale(c_filter.argument),
             WrFilterOpType::HueRotate => FilterOp::HueRotate(c_filter.argument),
             WrFilterOpType::Invert => FilterOp::Invert(c_filter.argument),
             WrFilterOpType::Opacity => FilterOp::Opacity(PropertyBinding::Value(c_filter.argument), c_filter.argument),
             WrFilterOpType::Saturate => FilterOp::Saturate(c_filter.argument),
             WrFilterOpType::Sepia => FilterOp::Sepia(c_filter.argument),
+            WrFilterOpType::DropShadow => FilterOp::DropShadow(c_filter.offset,
+                                                               c_filter.argument,
+                                                               c_filter.color),
         }
     }).collect();
 
     let opacity_ref = unsafe { opacity.as_ref() };
     if let Some(opacity) = opacity_ref {
         if *opacity < 1.0 {
             filters.push(FilterOp::Opacity(PropertyBinding::Value(*opacity), *opacity));
         }
--- a/gfx/webrender_bindings/webrender_ffi_generated.h
+++ b/gfx/webrender_bindings/webrender_ffi_generated.h
@@ -220,16 +220,17 @@ enum class WrFilterOpType : uint32_t {
   Brightness = 1,
   Contrast = 2,
   Grayscale = 3,
   HueRotate = 4,
   Invert = 5,
   Opacity = 6,
   Saturate = 7,
   Sepia = 8,
+  DropShadow = 9,
 
   Sentinel /* this must be last for serialization purposes. */
 };
 
 enum class YuvColorSpace : uint32_t {
   Rec601 = 0,
   Rec709 = 1,
 
@@ -686,20 +687,24 @@ struct WrAnimationProperty {
     return effect_type == aOther.effect_type &&
            id == aOther.id;
   }
 };
 
 struct WrFilterOp {
   WrFilterOpType filter_type;
   float argument;
+  LayoutVector2D offset;
+  ColorF color;
 
   bool operator==(const WrFilterOp& aOther) const {
     return filter_type == aOther.filter_type &&
-           argument == aOther.argument;
+           argument == aOther.argument &&
+           offset == aOther.offset &&
+           color == aOther.color;
   }
 };
 
 struct FontInstanceKey {
   IdNamespace mNamespace;
   uint32_t mHandle;
 
   bool operator==(const FontInstanceKey& aOther) const {
--- a/layout/painting/nsDisplayList.cpp
+++ b/layout/painting/nsDisplayList.cpp
@@ -9966,16 +9966,44 @@ nsDisplayFilter::CreateWebRenderCommands
           ClampStdDeviation(
             NSAppUnitsToFloatPixels(
               filter.GetFilterParameter().GetCoordValue(),
               appUnitsPerDevPixel)),
         };
         wrFilters.AppendElement(filterOp);
         break;
       }
+      case NS_STYLE_FILTER_DROP_SHADOW: {
+        float appUnitsPerDevPixel = mFrame->PresContext()->AppUnitsPerDevPixel();
+        nsCSSShadowArray* shadows = filter.GetDropShadow();
+        if (!shadows || shadows->Length() != 1) {
+          NS_NOTREACHED("Exactly one drop shadow should have been parsed.");
+          return false;
+        }
+
+        nsCSSShadowItem* shadow = shadows->ShadowAt(0);
+        nscolor color = shadow->mColor;
+        if (!shadow->mHasColor) {
+          color = mFrame->StyleColor()->mColor;
+        }
+
+        mozilla::wr::WrFilterOp filterOp = {
+          wr::ToWrFilterOpType(filter.GetType()),
+          NSAppUnitsToFloatPixels(shadow->mXOffset, appUnitsPerDevPixel),
+          NSAppUnitsToFloatPixels(shadow->mYOffset, appUnitsPerDevPixel),
+          NSAppUnitsToFloatPixels(shadow->mRadius, appUnitsPerDevPixel),
+          NS_GET_R(color) / 255.0f,
+          NS_GET_G(color) / 255.0f,
+          NS_GET_B(color) / 255.0f,
+          NS_GET_A(color) / 255.0f,
+        };
+
+        wrFilters.AppendElement(filterOp);
+        break;
+      }
       default:
         return false;
     }
   }
 
   float opacity = mFrame->StyleEffects()->mOpacity;
   StackingContextHelper sc(aSc, aBuilder, wrFilters, nullptr, 0, opacity != 1.0f && mHandleOpacity ? &opacity : nullptr);
 
--- a/layout/reftests/svg/filters/css-filter-chains/reftest.list
+++ b/layout/reftests/svg/filters/css-filter-chains/reftest.list
@@ -1,9 +1,9 @@
 # These tests verify that CSS filter chains behave properly.
 # e.g. filter: blur(3px) grayscale(0.5) invert(0.2);
 
 default-preferences pref(layout.css.filters.enabled,true)
 
 # Some platforms render this complex filter chain a little differently, and that's ok.
-fuzzy(5,13000) fuzzy-if(/^Windows\x20NT\x2010\.0/.test(http.oscpu)&&layersGPUAccelerated,35,13057) == long-chain.html long-chain-ref.html # Win10: Bug 1258241
+fails-if(webrender) fuzzy(5,13000) fuzzy-if(/^Windows\x20NT\x2010\.0/.test(http.oscpu)&&layersGPUAccelerated,35,13057) == long-chain.html long-chain-ref.html # Win10: Bug 1258241
 == moz-element.html moz-element-ref.html
 fuzzy-if(webrender,15-15,8262-8262) == same-filter.html same-filter-ref.html
--- a/layout/reftests/svg/filters/css-filters/reftest.list
+++ b/layout/reftests/svg/filters/css-filters/reftest.list
@@ -21,19 +21,19 @@ fuzzy-if(webrender,6-6,21308-21308) == b
 == brightness-zero.html brightness-zero-ref.html
 == containing-block-1.html containing-block-1-ref.html
 == contrast.html contrast-ref.html
 == contrast-extreme.html contrast-extreme-ref.html
 == contrast-one.html contrast-one-ref.html
 == contrast-percent.html contrast-percent-ref.html
 == contrast-reduce.html contrast-reduce-ref.html
 == contrast-zero.html contrast-zero-ref.html
-== drop-shadow.html drop-shadow-ref.html
-== drop-shadow-default-color.html drop-shadow-default-color-ref.html
-== drop-shadow-negative-offset.html drop-shadow-negative-offset-ref.html
+fuzzy-if(webrender,9-9,2625-2625) == drop-shadow.html drop-shadow-ref.html
+fuzzy-if(webrender,9-9,2625-2625) == drop-shadow-default-color.html drop-shadow-default-color-ref.html
+fuzzy-if(webrender,9-9,2625-2625) == drop-shadow-negative-offset.html drop-shadow-negative-offset-ref.html
 == filter-on-huge-bbox.html pass.svg
 == filter-on-outer-svg.html pass.svg
 fuzzy-if(webrender,1,10000) fuzzy-if(d2d,1,10000) == grayscale.html grayscale-ref.html
 fuzzy-if(webrender,1,10000) fuzzy-if(d2d,1,10000) == grayscale-one.html grayscale-one-ref.html
 fuzzy-if(webrender,1,10000) fuzzy-if(d2d,1,10000) fails-if(stylo&&webrender) == grayscale-over-one.html grayscale-over-one-ref.html
 fuzzy-if(webrender,1,10000) fuzzy-if(d2d,1,10000) == grayscale-percent.html grayscale-percent-ref.html
 fuzzy-if(webrender,1,10000) == grayscale-zero.html grayscale-zero-ref.html
 == hue-rotate.html hue-rotate-ref.html