Backout 47e84e1cc50f (bug 711043) due to crashtest & reftest crashes.
authorRyan VanderMeulen <ryanvm@gmail.com>
Mon, 19 Mar 2012 22:28:30 -0400
changeset 89788 09cc025b1f42f9782bba90c80ed9063f856429d1
parent 89787 47e84e1cc50f5dea0d0104d773b95633519637ac
child 89789 73456bef6c3199fc8c0cd3d071be34556977d72d
push id7320
push userryanvm@gmail.com
push dateTue, 20 Mar 2012 02:29:07 +0000
treeherdermozilla-inbound@09cc025b1f42 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs711043
milestone14.0a1
backs out47e84e1cc50f5dea0d0104d773b95633519637ac
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
Backout 47e84e1cc50f (bug 711043) due to crashtest & reftest crashes.
content/svg/content/src/nsSVGFilters.cpp
--- a/content/svg/content/src/nsSVGFilters.cpp
+++ b/content/svg/content/src/nsSVGFilters.cpp
@@ -3795,43 +3795,71 @@ nsSVGFEMorphologyElement::Filter(nsSVGFi
   }
   if (rx == 0 && ry == 0) {
     return NS_OK;
   }
 
   PRUint8* sourceData = aSources[0]->mImage->Data();
   PRUint8* targetData = aTarget->mImage->Data();
   PRUint32 stride = aTarget->mImage->Stride();
+  PRUint32 xExt[4], yExt[4];  // X, Y indices of RGBA extrema
   PRUint8 extrema[4];         // RGBA magnitude of extrema
   PRUint16 op = mEnumAttributes[OPERATOR].GetAnimValue();
 
-  // Scan the kernel for each pixel to determine max/min RGBA values.
+  /* Scan the kernel for each pixel to determine max/min RGBA values.  Note that
+   * as we advance in the x direction, each kernel overlaps the previous kernel.
+   * Thus, we can avoid iterating over the entire kernel by comparing the
+   * leading edge of the new kernel against the extrema found in the previous
+   * kernel.   We must still scan the entire kernel if the previous extrema do
+   * not fall within the current kernel or if we are starting a new row.
+   */
   for (PRInt32 y = rect.y; y < rect.YMost(); y++) {
     PRUint32 startY = NS_MAX(0, y - ry);
     // We need to read pixels not just in 'rect', which is limited to
     // the dirty part of our filter primitive subregion, but all pixels in
     // the given radii from the source surface, so use the surface size here.
     PRUint32 endY = NS_MIN(y + ry, instance->GetSurfaceHeight() - 1);
     for (PRInt32 x = rect.x; x < rect.XMost(); x++) {
       PRUint32 startX = NS_MAX(0, x - rx);
       PRUint32 endX = NS_MIN(x + rx, instance->GetSurfaceWidth() - 1);
       PRUint32 targIndex = y * stride + 4 * x;
 
-      for (PRUint32 i = 0; i < 4; i++) {
-        extrema[i] = sourceData[targIndex + i];
-      }
-      for (PRUint32 y1 = startY; y1 <= endY; y1++) {
-        for (PRUint32 x1 = startX; x1 <= endX; x1++) {
+      // We need to scan the entire kernel
+      if (x == rect.x || xExt[0]  <= startX || xExt[1] <= startX ||
+          xExt[2] <= startX || xExt[3] <= startX) {
+        PRUint32 i;
+        for (i = 0; i < 4; i++) {
+          extrema[i] = sourceData[targIndex + i];
+        }
+        for (PRUint32 y1 = startY; y1 <= endY; y1++) {
+          for (PRUint32 x1 = startX; x1 <= endX; x1++) {
+            for (i = 0; i < 4; i++) {
+              PRUint8 pixel = sourceData[y1 * stride + 4 * x1 + i];
+              if ((extrema[i] >= pixel &&
+                   op == nsSVGFEMorphologyElement::SVG_OPERATOR_ERODE) ||
+                  (extrema[i] <= pixel &&
+                   op == nsSVGFEMorphologyElement::SVG_OPERATOR_DILATE)) {
+                extrema[i] = pixel;
+                xExt[i] = x1;
+                yExt[i] = y1;
+              }
+            }
+          }
+        }
+      } else { // We only need to look at the newest column
+        for (PRUint32 y1 = startY; y1 <= endY; y1++) {
           for (PRUint32 i = 0; i < 4; i++) {
-            PRUint8 pixel = sourceData[y1 * stride + 4 * x1 + i];
-            if ((extrema[i] > pixel &&
+            PRUint8 pixel = sourceData[y1 * stride + 4 * endX + i];
+            if ((extrema[i] >= pixel &&
                  op == nsSVGFEMorphologyElement::SVG_OPERATOR_ERODE) ||
-                (extrema[i] < pixel &&
+                (extrema[i] <= pixel &&
                  op == nsSVGFEMorphologyElement::SVG_OPERATOR_DILATE)) {
-              extrema[i] = pixel;
+                extrema[i] = pixel;
+                xExt[i] = endX;
+                yExt[i] = y1;
             }
           }
         }
       }
       targetData[targIndex  ] = extrema[0];
       targetData[targIndex+1] = extrema[1];
       targetData[targIndex+2] = extrema[2];
       targetData[targIndex+3] = extrema[3];
@@ -5086,21 +5114,24 @@ nsSVGFELightingElement::Filter(nsSVGFilt
 
       if (spotLight) {
         float S[3];
         S[0] = pointsAt[0] - lightPos[0];
         S[1] = pointsAt[1] - lightPos[1];
         S[2] = pointsAt[2] - lightPos[2];
         NORMALIZE(S);
         float dot = -DOT(L, S);
-        if (dot < cosConeAngle) dot = 0;
-        float tmp = pow(dot, specularExponent);
-        color = NS_RGB(PRUint8(NS_GET_R(lightColor) * tmp),
-                       PRUint8(NS_GET_G(lightColor) * tmp),
-                       PRUint8(NS_GET_B(lightColor) * tmp));
+        if (dot < cosConeAngle) {
+          color = NS_RGB(0, 0, 0);
+        } else {
+          float tmp = pow(dot, specularExponent);
+          color = NS_RGB(PRUint8(NS_GET_R(lightColor) * tmp),
+                         PRUint8(NS_GET_G(lightColor) * tmp),
+                         PRUint8(NS_GET_B(lightColor) * tmp));
+        }
       } else {
         color = lightColor;
       }
 
       LightPixel(N, L, color, targetData + index);
     }
   }
 
@@ -5257,24 +5288,29 @@ nsSVGFEDiffuseLightingElement::Attribute
 
 void
 nsSVGFEDiffuseLightingElement::LightPixel(const float *N, const float *L,
                                           nscolor color, PRUint8 *targetData)
 {
   float diffuseNL =
     mNumberAttributes[DIFFUSE_CONSTANT].GetAnimValue() * DOT(N, L);
 
-  if (diffuseNL < 0) diffuseNL = 0;
-
-  targetData[GFX_ARGB32_OFFSET_B] =
-    NS_MIN(PRUint32(diffuseNL * NS_GET_B(color)), 255U);
-  targetData[GFX_ARGB32_OFFSET_G] =
-    NS_MIN(PRUint32(diffuseNL * NS_GET_G(color)), 255U);
-  targetData[GFX_ARGB32_OFFSET_R] =
-    NS_MIN(PRUint32(diffuseNL * NS_GET_R(color)), 255U);
+  if (diffuseNL > 0) {
+    targetData[GFX_ARGB32_OFFSET_B] =
+      NS_MIN(PRUint32(diffuseNL * NS_GET_B(color)), 255U);
+    targetData[GFX_ARGB32_OFFSET_G] =
+      NS_MIN(PRUint32(diffuseNL * NS_GET_G(color)), 255U);
+    targetData[GFX_ARGB32_OFFSET_R] =
+      NS_MIN(PRUint32(diffuseNL * NS_GET_R(color)), 255U);
+  } else {
+    targetData[GFX_ARGB32_OFFSET_B] = 0;
+    targetData[GFX_ARGB32_OFFSET_G] = 0;
+    targetData[GFX_ARGB32_OFFSET_R] = 0;
+  }
+
   targetData[GFX_ARGB32_OFFSET_A] = 255;
 }
 
 //---------------------SpecularLighting------------------------
 
 typedef nsSVGFELightingElement nsSVGFESpecularLightingElementBase;
 
 class nsSVGFESpecularLightingElement : public nsSVGFESpecularLightingElementBase,
@@ -5419,34 +5455,37 @@ nsSVGFESpecularLightingElement::LightPix
   H[0] = L[0];
   H[1] = L[1];
   H[2] = L[2] + 1;
   NORMALIZE(H);
 
   float kS = mNumberAttributes[SPECULAR_CONSTANT].GetAnimValue();
   float dotNH = DOT(N, H);
 
-  bool invalid = dotNH <= 0 || kS <= 0;
-  kS *= invalid ? 0 : 1;
-  PRUint8 minAlpha = invalid ? 255 : 0;
-
-  float specularNH =
-    kS * pow(dotNH, mNumberAttributes[SPECULAR_EXPONENT].GetAnimValue());
-
-  targetData[GFX_ARGB32_OFFSET_B] =
-    NS_MIN(PRUint32(specularNH * NS_GET_B(color)), 255U);
-  targetData[GFX_ARGB32_OFFSET_G] =
-    NS_MIN(PRUint32(specularNH * NS_GET_G(color)), 255U);
-  targetData[GFX_ARGB32_OFFSET_R] =
-    NS_MIN(PRUint32(specularNH * NS_GET_R(color)), 255U);
-
-  targetData[GFX_ARGB32_OFFSET_A] =
-    NS_MAX(minAlpha, NS_MAX(targetData[GFX_ARGB32_OFFSET_B],
-                            NS_MAX(targetData[GFX_ARGB32_OFFSET_G],
-                                   targetData[GFX_ARGB32_OFFSET_R])));
+  if (dotNH > 0 && kS > 0) {
+    float specularNH =
+      kS * pow(dotNH, mNumberAttributes[SPECULAR_EXPONENT].GetAnimValue());
+
+    targetData[GFX_ARGB32_OFFSET_B] =
+      NS_MIN(PRUint32(specularNH * NS_GET_B(color)), 255U);
+    targetData[GFX_ARGB32_OFFSET_G] =
+      NS_MIN(PRUint32(specularNH * NS_GET_G(color)), 255U);
+    targetData[GFX_ARGB32_OFFSET_R] =
+      NS_MIN(PRUint32(specularNH * NS_GET_R(color)), 255U);
+
+    targetData[GFX_ARGB32_OFFSET_A] =
+      NS_MAX(targetData[GFX_ARGB32_OFFSET_B],
+             NS_MAX(targetData[GFX_ARGB32_OFFSET_G],
+                    targetData[GFX_ARGB32_OFFSET_R]));
+  } else {
+    targetData[GFX_ARGB32_OFFSET_B] = 0;
+    targetData[GFX_ARGB32_OFFSET_G] = 0;
+    targetData[GFX_ARGB32_OFFSET_R] = 0;
+    targetData[GFX_ARGB32_OFFSET_A] = 255;
+  }
 }
 
 //---------------------Image------------------------
 
 nsSVGElement::StringInfo nsSVGFEImageElement::sStringInfo[2] =
 {
   { &nsGkAtoms::result, kNameSpaceID_None, true },
   { &nsGkAtoms::href, kNameSpaceID_XLink, true }
@@ -5945,18 +5984,16 @@ nsSVGFEDisplacementMapElement::Filter(ns
   PRInt32 width = instance->GetSurfaceWidth();
   PRInt32 height = instance->GetSurfaceHeight();
 
   PRUint8* sourceData = aSources[0]->mImage->Data();
   PRUint8* displacementData = aSources[1]->mImage->Data();
   PRUint8* targetData = aTarget->mImage->Data();
   PRUint32 stride = aTarget->mImage->Stride();
 
-  static PRUint8 dummyData[1] = { 0 };
-
   static const PRUint16 channelMap[5] = {
                              0,
                              GFX_ARGB32_OFFSET_R,
                              GFX_ARGB32_OFFSET_G,
                              GFX_ARGB32_OFFSET_B,
                              GFX_ARGB32_OFFSET_A };
   PRUint16 xChannel = channelMap[mEnumAttributes[CHANNEL_X].GetAnimValue()];
   PRUint16 yChannel = channelMap[mEnumAttributes[CHANNEL_Y].GetAnimValue()];
@@ -5969,30 +6006,23 @@ nsSVGFEDisplacementMapElement::Filter(ns
       PRUint32 targIndex = y * stride + 4 * x;
       // At some point we might want to replace this with a bilinear sample.
       PRInt32 sourceX = x +
         NSToIntFloor(scaleOver255 * displacementData[targIndex + xChannel] +
                 scaleAdjustment);
       PRInt32 sourceY = y +
         NSToIntFloor(scaleOver255 * displacementData[targIndex + yChannel] +
                 scaleAdjustment);
-
-      bool outOfBounds = sourceX < 0 || sourceX >= width ||
-                         sourceY < 0 || sourceY >= height;
-      PRUint8* data;
-      PRInt32 multiplier;
-      if (outOfBounds) {
-        data = sourceData;
-        multiplier = 1;
+      if (sourceX < 0 || sourceX >= width ||
+          sourceY < 0 || sourceY >= height) {
+        *(PRUint32*)(targetData + targIndex) = 0;
       } else {
-        data = dummyData;
-        multiplier = 0;
+        *(PRUint32*)(targetData + targIndex) =
+          *(PRUint32*)(sourceData + sourceY * stride + 4 * sourceX);
       }
-      *(PRUint32*)(targetData + targIndex) =
-        *(PRUint32*)(data + multiplier * (sourceY * stride + 4 * sourceX));
     }
   }
   return NS_OK;
 }
 
 bool
 nsSVGFEDisplacementMapElement::AttributeAffectsRendering(PRInt32 aNameSpaceID,
                                                          nsIAtom* aAttribute) const