Bug 1203376 - Honor filter region settings for lighting filters. r=mstange
authorTom Klein <twointofive@gmail.com>
Wed, 07 Oct 2015 08:25:00 +0200
changeset 266766 2873ffc036efddbafb37e4181c6b53a5439ee2a1
parent 266765 ca9e63379f6ab2d5093276cc2641f1c775149932
child 266767 189ab4d27daf760a4f5be489d7f860ceb97eebd7
push id66289
push usercbook@mozilla.com
push dateThu, 08 Oct 2015 09:35:50 +0000
treeherdermozilla-inbound@2873ffc036ef [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmstange
bugs1203376
milestone44.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1203376 - Honor filter region settings for lighting filters. r=mstange
gfx/2d/FilterNodeD2D1.cpp
gfx/2d/FilterNodeSoftware.cpp
gfx/src/FilterSupport.cpp
gfx/src/FilterSupport.h
layout/reftests/svg/filters/feDiffuseLighting-1-ref.svg
layout/reftests/svg/filters/filter-lighting-region-ref.svg
layout/reftests/svg/filters/filter-lighting-region.svg
layout/reftests/svg/filters/reftest.list
--- a/gfx/2d/FilterNodeD2D1.cpp
+++ b/gfx/2d/FilterNodeD2D1.cpp
@@ -531,16 +531,37 @@ IsTransferFilterType(FilterType aType)
     case FilterType::TABLE_TRANSFER:
     case FilterType::DISCRETE_TRANSFER:
       return true;
     default:
       return false;
   }
 }
 
+static bool
+HasUnboundedOutputRegion(FilterType aType)
+{
+  if (IsTransferFilterType(aType)) {
+    return true;
+  }
+
+  switch (aType) {
+    case FilterType::COLOR_MATRIX:
+    case FilterType::POINT_DIFFUSE:
+    case FilterType::SPOT_DIFFUSE:
+    case FilterType::DISTANT_DIFFUSE:
+    case FilterType::POINT_SPECULAR:
+    case FilterType::SPOT_SPECULAR:
+    case FilterType::DISTANT_SPECULAR:
+      return true;
+    default:
+      return false;
+  }
+}
+
 /* static */
 already_AddRefed<FilterNode>
 FilterNodeD2D1::Create(ID2D1DeviceContext *aDC, FilterType aType)
 {
   if (aType == FilterType::CONVOLVE_MATRIX) {
     return MakeAndAddRef<FilterNodeConvolveD2D1>(aDC);
   }
 
@@ -551,17 +572,17 @@ FilterNodeD2D1::Create(ID2D1DeviceContex
 
   if (FAILED(hr) || !effect) {
     gfxCriticalErrorOnce() << "Failed to create effect for FilterType: " << hexa(hr);
     return nullptr;
   }
 
   RefPtr<FilterNodeD2D1> filter = new FilterNodeD2D1(effect, aType);
 
-  if (IsTransferFilterType(aType) || aType == FilterType::COLOR_MATRIX) {
+  if (HasUnboundedOutputRegion(aType)) {
     // These filters can produce non-transparent output from transparent
     // input pixels, and we want them to have an unbounded output region.
     filter = new FilterNodeExtendInputAdapterD2D1(aDC, filter, aType);
   }
 
   if (IsTransferFilterType(aType)) {
     // Component transfer filters should appear to apply on unpremultiplied
     // colors, but the D2D1 effects apply on premultiplied colors.
--- a/gfx/2d/FilterNodeSoftware.cpp
+++ b/gfx/2d/FilterNodeSoftware.cpp
@@ -3335,17 +3335,17 @@ FilterNodeLightingSoftware<LightType, Li
   mColor = aColor;
   Invalidate();
 }
 
 template<typename LightType, typename LightingType>
 IntRect
 FilterNodeLightingSoftware<LightType, LightingType>::GetOutputRectInRect(const IntRect& aRect)
 {
-  return GetInputRectInRect(IN_LIGHTING_IN, aRect);
+  return aRect;
 }
 
 Point3D
 PointLightSoftware::GetVectorToLight(const Point3D &aTargetPoint)
 {
   return Normalized(mPosition - aTargetPoint);
 }
 
@@ -3477,17 +3477,17 @@ FilterNodeLightingSoftware<LightType, Li
                   ceil(float(aKernelUnitLengthY)));
 
   // Inflate the source rect by another pixel because the bilinear filtering in
   // ColorComponentAtPoint may want to access the margins.
   srcRect.Inflate(1);
 
   RefPtr<DataSourceSurface> input =
     GetInputDataSourceSurface(IN_LIGHTING_IN, srcRect, CAN_HANDLE_A8,
-                              EDGE_MODE_DUPLICATE);
+                              EDGE_MODE_NONE);
 
   if (!input) {
     return nullptr;
   }
 
   if (input->GetFormat() != SurfaceFormat::A8) {
     input = FilterProcessing::ExtractAlpha(input);
   }
--- a/gfx/src/FilterSupport.cpp
+++ b/gfx/src/FilterSupport.cpp
@@ -1227,19 +1227,16 @@ FilterNodeGraphFromDescription(DrawTarge
                                SourceSurface* aFillPaint,
                                const IntRect& aFillPaintRect,
                                SourceSurface* aStrokePaint,
                                const IntRect& aStrokePaintRect,
                                nsTArray<RefPtr<SourceSurface>>& aAdditionalImages)
 {
   const nsTArray<FilterPrimitiveDescription>& primitives = aFilter.mPrimitives;
 
-  Rect resultNeededRect(aResultNeededRect);
-  resultNeededRect.RoundOut();
-
   RefPtr<FilterCachedColorModels> sourceFilters[4];
   nsTArray<RefPtr<FilterCachedColorModels> > primitiveFilters;
 
   for (size_t i = 0; i < primitives.Length(); ++i) {
     const FilterPrimitiveDescription& descr = primitives[i];
 
     nsTArray<RefPtr<FilterNode> > inputFilterNodes;
     nsTArray<IntRect> inputSourceRects;
@@ -1402,16 +1399,19 @@ ResultChangeRegionForPrimitive(const Fil
       return aInputChangeRegions[0].Inflated(nsIntMargin(ry, rx, ry, rx));
     }
 
     case PrimitiveType::Tile:
       return aDescription.PrimitiveSubregion();
 
     case PrimitiveType::ConvolveMatrix:
     {
+      if (atts.GetUint(eConvolveMatrixEdgeMode) != EDGE_MODE_NONE) {
+        return aDescription.PrimitiveSubregion();
+      }
       Size kernelUnitLength = atts.GetSize(eConvolveMatrixKernelUnitLength);
       IntSize kernelSize = atts.GetIntSize(eConvolveMatrixKernelSize);
       IntPoint target = atts.GetIntPoint(eConvolveMatrixTarget);
       nsIntMargin m(ceil(kernelUnitLength.width * (target.x)),
                     ceil(kernelUnitLength.height * (target.y)),
                     ceil(kernelUnitLength.width * (kernelSize.width - target.x - 1)),
                     ceil(kernelUnitLength.height * (kernelSize.height - target.y - 1)));
       return aInputChangeRegions[0].Inflated(m);
@@ -1598,16 +1598,18 @@ FilterSupport::PostFilterExtentsForPrimi
       if (ResultOfZeroUnderTransferFunction(functionAttributes) > 0.0f) {
         return aDescription.PrimitiveSubregion();
       }
       return aInputExtents[0];
     }
 
     case PrimitiveType::Turbulence:
     case PrimitiveType::Image:
+    case PrimitiveType::DiffuseLighting:
+    case PrimitiveType::SpecularLighting:
     {
       return aDescription.PrimitiveSubregion();
     }
 
     case PrimitiveType::Morphology:
     {
       uint32_t op = atts.GetUint(eMorphologyOperator);
       if (op == SVG_OPERATOR_ERODE) {
--- a/gfx/src/FilterSupport.h
+++ b/gfx/src/FilterSupport.h
@@ -432,17 +432,18 @@ public:
                           SourceSurface* aStrokePaint,
                           const IntRect& aStrokePaintRect,
                           nsTArray<RefPtr<SourceSurface>>& aAdditionalImages,
                           const Point& aDestPoint,
                           const DrawOptions& aOptions = DrawOptions());
 
   /**
    * Computes the region that changes in the filter output due to a change in
-   * input.
+   * input.  This is primarily needed when an individual piece of content inside
+   * a filtered container element changes.
    */
   static nsIntRegion
   ComputeResultChangeRegion(const FilterDescription& aFilter,
                             const nsIntRegion& aSourceGraphicChange,
                             const nsIntRegion& aFillPaintChange,
                             const nsIntRegion& aStrokePaintChange);
 
   /**
--- a/layout/reftests/svg/filters/feDiffuseLighting-1-ref.svg
+++ b/layout/reftests/svg/filters/feDiffuseLighting-1-ref.svg
@@ -1,7 +1,16 @@
 <!--
      Any copyright is dedicated to the Public Domain.
      http://creativecommons.org/publicdomain/zero/1.0/
 -->
 <svg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'>
-  <image width='100' height='100' xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAYAAABw4pVUAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAG6SURBVHhe7d3BbcJAGAXhJYXQg32mCV8p2vRAEb4mREoJe/g2GiTf55/hiRu+jTG+P08fxMAXwhHGn4GCYF+FghQEM4DhtJCCYAYwnBZSEMwAhtNCCoIZwHBaSEEwAxhOCykIZgDDaSEFwQxgOC2kIJgBDGfqQh6Px9j3HTtxLZypQZ7P5ziOYy0DGO3UIPf7fWzbhp24Fs7UIGudbtIWBOtSkIJgBjCcFlIQzACG00IKghnAcFpIQTADGE4LKQhmAMNpIQXBDGA4LaQgmAEMp4UUBDOA4bSQgmAGMJwWUhDMAIbTQgqCGcBwWkhBMAMYTgspCGYAw2khBcEMYDgtpCCYAQynhRQEM4DhtJCCYAYwnBZSEMwAhtNCCoIZwHBaSEEwAxhOCykIZgDDaSEFwQxgOC2kIJgBDKeFFAQzgOG0kIJgBjCcFlIQzACG00IKghnAcFrIfw7yfr/H6/XCTlwL5/bBnfY+9d8/47+ua5znuZYFiHZqEOiuZVH6DcHSFaQgmAEMp4UUBDOA4bSQgmAGMJwWUhDMAIbTQgqCGcBwWkhBMAMYTgspCGYAw2khBcEMYDgtBAvyA+wPEw79WuphAAAAAElFTkSuQmCC"/>
+  <image width='100' height='100'
+         xlink:href="data:image/png;base64,
+iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAYAAABw4pVUAAAABmJLR0QA/wD/AP+gvaeTAAAACXBI
+WXMAAA7EAAAOxAGVKw4bAAAAB3RJTUUH3wkbDDIilL5aRAAAAB1pVFh0Q29tbWVudAAAAAAAQ3Jl
+YXRlZCB3aXRoIEdJTVBkLmUHAAAA9UlEQVR42u3csRHDIBBFwbPHddADiqmEduhFlSiWelBOSirX
+YFsB49lXAMHf4DIeEXGFpqi1Fk8zzFPOGchsAQEiIEAEBIiAABEQIAIiIEAEBIiAAPmgUkosy2LV
+H3rd+VitNXrvse+7ZWcASSlFSsmqbggQAQEiIAICRECACAgQAQEiIEAERECACAgQAQEiIEAERECA
+CAgQAQEiIEAERECACAgQAQEiIEAERECACAgQAQEiIEAERECACAgQAfnHbv3Z+jzP6L1bdRaQdV1j
+jGHVWUC2bbOoGwJEQIAIiIAAERAgAgJEQIAIiIAAERAg+qrjOOINBcEbJFN4kugAAAAASUVORK5C
+YII="/>
 </svg>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/filters/filter-lighting-region-ref.svg
@@ -0,0 +1,11 @@
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<svg xmlns="http://www.w3.org/2000/svg" width="600px" height="300px">
+
+  <rect x="50" y="50" width="200" height="200" fill="black" />
+
+  <rect x="340" y="40" width="220" height="220" fill="grey" />
+  <rect x="350" y="50" width="200" height="200" fill="white" />
+</svg>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/filters/filter-lighting-region.svg
@@ -0,0 +1,30 @@
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<svg xmlns="http://www.w3.org/2000/svg" width="600px" height="300px">
+  <!-- From https://bugzilla.mozilla.org/show_bug.cgi?id=1203376 -->
+  <defs>
+    <!-- the filter lights are intentionally chosen to fill the entire area with
+         a solid color since we're only testing the extents of the filter region
+    -->
+    <filter id="diffuse" x="-50%" y="-50%" width="200%" height="200%">
+      <!-- gives a black filter region -->
+      <feDiffuseLighting lighting-color="black">
+        <feDistantLight />
+      </feDiffuseLighting>
+    </filter>
+
+    <filter id="specular" x="-50%" y="-50%" width="200%" height="200%">
+      <!-- gives a white filter region -->
+      <feSpecularLighting lighting-color="white" specularConstant="100">
+        <feDistantLight elevation="90"/>
+      </feSpecularLighting>
+    </filter>
+  </defs>
+
+  <rect x="100" y="100" width="100" height="100" filter="url(#diffuse)" />
+
+  <rect x="340" y="40" width="220" height="220" fill="grey" />
+  <rect x="400" y="100" width="100" height="100" filter="url(#specular)" />
+</svg>
--- a/layout/reftests/svg/filters/reftest.list
+++ b/layout/reftests/svg/filters/reftest.list
@@ -104,19 +104,21 @@ fuzzy(2,500) == feDisplacementMap-colour
 == feMorphology-radius-negative-02.svg pass.svg
 == feMorphology-radius-zero-01.svg pass.svg
 == feMorphology-radius-zero-02.svg pass.svg
 
 == feTile-large-01.svg pass.svg
 == feTile-large-02.svg feTile-large-02-ref.svg
 == feTile-outside-01.svg feTile-outside-01-ref.svg
 
-fuzzy(1,119) == feDiffuseLighting-1.svg feDiffuseLighting-1-ref.svg
+fuzzy(1,217) == feDiffuseLighting-1.svg feDiffuseLighting-1-ref.svg
 
 fuzzy(2,2659) skip-if(d2d) == feSpecularLighting-1.svg feSpecularLighting-1-ref.svg
 
+== filter-lighting-region.svg filter-lighting-region-ref.svg
+
 == fePointLight-zoomed-page.svg fePointLight-zoomed-page-ref.svg
 
 == feTurbulence-offset.svg feTurbulence-offset-ref.svg
 
 == outside-sourcegraphic-1.svg outside-sourcegraphic-ref.svg
 == outside-sourcegraphic-2.svg outside-sourcegraphic-ref.svg
 == outside-sourcegraphic-3.svg outside-sourcegraphic-ref.svg