Title: [225122] trunk/Source/WebCore
Revision
225122
Author
simon.fra...@apple.com
Date
2017-11-23 14:20:09 -0800 (Thu, 23 Nov 2017)

Log Message

FELighting cleanup and optimization
https://bugs.webkit.org/show_bug.cgi?id=179933

Reviewed by Darin Adler.

Make FELighting about 25% faster by maintaining an "alpha" window of the alpha
values of the 9 pixels surrounding the current pixel, and sliding this window over
when moving to the next pixel. This avoids reading the same alpha values from the original
buffer multiple times.

Clean up LightSource and subclasses, adding SPECIALIZE_TYPE_TRAITS macros,
and turning updatePaintingData() into a function with no side effects that returns
the required data.

Remove explicit 'inline' keywords, allowing the compiler to make inlining decisions.

* platform/graphics/cpu/arm/filters/FELightingNEON.h:
(WebCore::FELighting::platformApplyNeon):
* platform/graphics/filters/DistantLightSource.cpp:
(WebCore::DistantLightSource::initPaintingData):
(WebCore::DistantLightSource::computePixelLightingData const):
(WebCore::DistantLightSource::updatePaintingData): Deleted.
* platform/graphics/filters/DistantLightSource.h:
* platform/graphics/filters/FELighting.cpp:
(WebCore::FELighting::LightingData::interiorNormal const):
(WebCore::FELighting::setPixel):
(WebCore::FELighting::setPixelInternal):
(WebCore::FELighting::platformApplyGenericPaint):
(WebCore::FELighting::platformApplyGeneric):
(WebCore::FELighting::platformApply):
(WebCore::FELighting::drawLighting):
(WebCore::FELighting::inlineSetPixel): Deleted.
* platform/graphics/filters/FELighting.h:
(WebCore::FELighting::AlphaWindow::topLeft const):
(WebCore::FELighting::AlphaWindow::left const):
(WebCore::FELighting::AlphaWindow::bottomLeft const):
(WebCore::FELighting::AlphaWindow::top const):
(WebCore::FELighting::AlphaWindow::center const):
(WebCore::FELighting::AlphaWindow::bottom const):
(WebCore::FELighting::AlphaWindow::setTop):
(WebCore::FELighting::AlphaWindow::setCenter):
(WebCore::FELighting::AlphaWindow::setBottom):
(WebCore::FELighting::AlphaWindow::setTopRight):
(WebCore::FELighting::AlphaWindow::setRight):
(WebCore::FELighting::AlphaWindow::setBottomRight):
(WebCore::FELighting::AlphaWindow::shiftRow):
(WebCore::FELighting::AlphaWindow::shift):
* platform/graphics/filters/LightSource.h:
* platform/graphics/filters/PointLightSource.cpp:
(WebCore::PointLightSource::computePixelLightingData const):
(WebCore::PointLightSource::updatePaintingData): Deleted.
* platform/graphics/filters/PointLightSource.h:
* platform/graphics/filters/SpotLightSource.cpp:
(WebCore::SpotLightSource::initPaintingData):
(WebCore::SpotLightSource::computePixelLightingData const):
(WebCore::SpotLightSource::updatePaintingData): Deleted.
* platform/graphics/filters/SpotLightSource.h:

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (225121 => 225122)


--- trunk/Source/WebCore/ChangeLog	2017-11-23 21:33:44 UTC (rev 225121)
+++ trunk/Source/WebCore/ChangeLog	2017-11-23 22:20:09 UTC (rev 225122)
@@ -1,5 +1,65 @@
 2017-11-23  Simon Fraser  <simon.fra...@apple.com>
 
+        FELighting cleanup and optimization
+        https://bugs.webkit.org/show_bug.cgi?id=179933
+
+        Reviewed by Darin Adler.
+
+        Make FELighting about 25% faster by maintaining an "alpha" window of the alpha
+        values of the 9 pixels surrounding the current pixel, and sliding this window over
+        when moving to the next pixel. This avoids reading the same alpha values from the original
+        buffer multiple times.
+
+        Clean up LightSource and subclasses, adding SPECIALIZE_TYPE_TRAITS macros,
+        and turning updatePaintingData() into a function with no side effects that returns
+        the required data.
+
+        Remove explicit 'inline' keywords, allowing the compiler to make inlining decisions.
+
+        * platform/graphics/cpu/arm/filters/FELightingNEON.h:
+        (WebCore::FELighting::platformApplyNeon):
+        * platform/graphics/filters/DistantLightSource.cpp:
+        (WebCore::DistantLightSource::initPaintingData):
+        (WebCore::DistantLightSource::computePixelLightingData const):
+        (WebCore::DistantLightSource::updatePaintingData): Deleted.
+        * platform/graphics/filters/DistantLightSource.h:
+        * platform/graphics/filters/FELighting.cpp:
+        (WebCore::FELighting::LightingData::interiorNormal const):
+        (WebCore::FELighting::setPixel):
+        (WebCore::FELighting::setPixelInternal):
+        (WebCore::FELighting::platformApplyGenericPaint):
+        (WebCore::FELighting::platformApplyGeneric):
+        (WebCore::FELighting::platformApply):
+        (WebCore::FELighting::drawLighting):
+        (WebCore::FELighting::inlineSetPixel): Deleted.
+        * platform/graphics/filters/FELighting.h:
+        (WebCore::FELighting::AlphaWindow::topLeft const):
+        (WebCore::FELighting::AlphaWindow::left const):
+        (WebCore::FELighting::AlphaWindow::bottomLeft const):
+        (WebCore::FELighting::AlphaWindow::top const):
+        (WebCore::FELighting::AlphaWindow::center const):
+        (WebCore::FELighting::AlphaWindow::bottom const):
+        (WebCore::FELighting::AlphaWindow::setTop):
+        (WebCore::FELighting::AlphaWindow::setCenter):
+        (WebCore::FELighting::AlphaWindow::setBottom):
+        (WebCore::FELighting::AlphaWindow::setTopRight):
+        (WebCore::FELighting::AlphaWindow::setRight):
+        (WebCore::FELighting::AlphaWindow::setBottomRight):
+        (WebCore::FELighting::AlphaWindow::shiftRow):
+        (WebCore::FELighting::AlphaWindow::shift):
+        * platform/graphics/filters/LightSource.h:
+        * platform/graphics/filters/PointLightSource.cpp:
+        (WebCore::PointLightSource::computePixelLightingData const):
+        (WebCore::PointLightSource::updatePaintingData): Deleted.
+        * platform/graphics/filters/PointLightSource.h:
+        * platform/graphics/filters/SpotLightSource.cpp:
+        (WebCore::SpotLightSource::initPaintingData):
+        (WebCore::SpotLightSource::computePixelLightingData const):
+        (WebCore::SpotLightSource::updatePaintingData): Deleted.
+        * platform/graphics/filters/SpotLightSource.h:
+
+2017-11-23  Simon Fraser  <simon.fra...@apple.com>
+
         Add support for CanvasPattern.setTransform()
         https://bugs.webkit.org/show_bug.cgi?id=179935
 

Modified: trunk/Source/WebCore/platform/graphics/cpu/arm/filters/FELightingNEON.h (225121 => 225122)


--- trunk/Source/WebCore/platform/graphics/cpu/arm/filters/FELightingNEON.h	2017-11-23 21:33:44 UTC (rev 225121)
+++ trunk/Source/WebCore/platform/graphics/cpu/arm/filters/FELightingNEON.h	2017-11-23 22:20:09 UTC (rev 225122)
@@ -93,7 +93,7 @@
 void neonDrawLighting(FELightingPaintingDataForNeon*);
 }
 
-inline void FELighting::platformApplyNeon(LightingData& data, LightSource::PaintingData& paintingData)
+inline void FELighting::platformApplyNeon(const LightingData& data, const LightSource::PaintingData& paintingData)
 {
     FELightingFloatArgumentsForNeon floatArguments __attribute__((__aligned__(16)));
     FELightingPaintingDataForNeon neonData = {

Modified: trunk/Source/WebCore/platform/graphics/filters/DistantLightSource.cpp (225121 => 225122)


--- trunk/Source/WebCore/platform/graphics/filters/DistantLightSource.cpp	2017-11-23 21:33:44 UTC (rev 225121)
+++ trunk/Source/WebCore/platform/graphics/filters/DistantLightSource.cpp	2017-11-23 22:20:09 UTC (rev 225122)
@@ -39,14 +39,17 @@
 {
     float azimuth = deg2rad(m_azimuth);
     float elevation = deg2rad(m_elevation);
-    paintingData.lightVector.setX(cosf(azimuth) * cosf(elevation));
-    paintingData.lightVector.setY(sinf(azimuth) * cosf(elevation));
-    paintingData.lightVector.setZ(sinf(elevation));
-    paintingData.lightVectorLength = 1;
+    paintingData.intialLightingData.lightVector = {
+        std::cos(azimuth) * std::cos(elevation),
+        std::sin(azimuth) * std::cos(elevation),
+        std::sin(elevation)
+    };
+    paintingData.intialLightingData.lightVectorLength = 1;
 }
 
-void DistantLightSource::updatePaintingData(PaintingData&, int, int, float)
+LightSource::ComputedLightingData DistantLightSource::computePixelLightingData(const PaintingData& paintingData, int, int, float) const
 {
+    return paintingData.intialLightingData;
 }
 
 bool DistantLightSource::setAzimuth(float azimuth)

Modified: trunk/Source/WebCore/platform/graphics/filters/DistantLightSource.h (225121 => 225122)


--- trunk/Source/WebCore/platform/graphics/filters/DistantLightSource.h	2017-11-23 21:33:44 UTC (rev 225121)
+++ trunk/Source/WebCore/platform/graphics/filters/DistantLightSource.h	2017-11-23 22:20:09 UTC (rev 225122)
@@ -20,8 +20,7 @@
  * Boston, MA 02110-1301, USA.
  */
 
-#ifndef DistantLightSource_h
-#define DistantLightSource_h
+#pragma once
 
 #include "LightSource.h"
 #include <wtf/Ref.h>
@@ -35,6 +34,7 @@
         return adoptRef(*new DistantLightSource(azimuth, elevation));
     }
 
+    // These are in degrees.
     float azimuth() const { return m_azimuth; }
     float elevation() const { return m_elevation; }
 
@@ -42,7 +42,7 @@
     bool setElevation(float) override;
 
     void initPaintingData(PaintingData&) override;
-    void updatePaintingData(PaintingData&, int x, int y, float z) override;
+    ComputedLightingData computePixelLightingData(const PaintingData&, int x, int y, float z) const final;
 
     WTF::TextStream& externalRepresentation(WTF::TextStream&) const override;
 
@@ -60,4 +60,4 @@
 
 } // namespace WebCore
 
-#endif // DistantLightSource_h
+SPECIALIZE_TYPE_TRAITS_LIGHTSOURCE(DistantLightSource, LS_DISTANT)

Modified: trunk/Source/WebCore/platform/graphics/filters/FELighting.cpp (225121 => 225122)


--- trunk/Source/WebCore/platform/graphics/filters/FELighting.cpp	2017-11-23 21:33:44 UTC (rev 225121)
+++ trunk/Source/WebCore/platform/graphics/filters/FELighting.cpp	2017-11-23 22:20:09 UTC (rev 225122)
@@ -84,7 +84,7 @@
 
 const static int cPixelSize = 4;
 const static int cAlphaChannelOffset = 3;
-const static unsigned char cOpaqueAlpha = static_cast<unsigned char>(0xff);
+const static uint8_t cOpaqueAlpha = static_cast<uint8_t>(0xFF);
 
 // These factors and the normal coefficients come from the table under https://www.w3.org/TR/SVG/filters.html#feDiffuseLightingElement.
 const static float cFactor1div2 = -1 / 2.f;
@@ -149,18 +149,30 @@
     };
 }
 
-inline IntSize FELighting::LightingData::interiorNormal(int offset) const
+inline IntSize FELighting::LightingData::interiorNormal(int offset, AlphaWindow& alphaWindow) const
 {
-    int left = static_cast<int>(pixels->item(offset - cPixelSize + cAlphaChannelOffset));
-    int right = static_cast<int>(pixels->item(offset + cPixelSize + cAlphaChannelOffset));
-    offset -= widthMultipliedByPixelSize;
-    int topLeft = static_cast<int>(pixels->item(offset - cPixelSize + cAlphaChannelOffset));
-    int top = static_cast<int>(pixels->item(offset + cAlphaChannelOffset));
-    int topRight = static_cast<int>(pixels->item(offset + cPixelSize + cAlphaChannelOffset));
-    offset += 2 * widthMultipliedByPixelSize;
-    int bottomLeft = static_cast<int>(pixels->item(offset - cPixelSize + cAlphaChannelOffset));
-    int bottom = static_cast<int>(pixels->item(offset + cAlphaChannelOffset));
-    int bottomRight = static_cast<int>(pixels->item(offset + cPixelSize + cAlphaChannelOffset));
+    int rightAlphaOffset = offset + cPixelSize + cAlphaChannelOffset;
+    
+    int right = static_cast<int>(pixels->item(rightAlphaOffset));
+    int topRight = static_cast<int>(pixels->item(rightAlphaOffset - widthMultipliedByPixelSize));
+    int bottomRight = static_cast<int>(pixels->item(rightAlphaOffset + widthMultipliedByPixelSize));
+
+    int left = alphaWindow.left();
+    int topLeft = alphaWindow.topLeft();
+    int top = alphaWindow.top();
+
+    int bottomLeft = alphaWindow.bottomLeft();
+    int bottom = alphaWindow.bottom();
+
+    // The alphaWindow has been shifted, and here we fill in the right column.
+    alphaWindow.alpha[0][2] = topRight;
+    alphaWindow.alpha[1][2] = right;
+    alphaWindow.alpha[2][2] = bottomRight;
+    
+    // Check that the alphaWindow is working with some spot-checks.
+    ASSERT(alphaWindow.topLeft() == pixels->item(offset - cPixelSize - widthMultipliedByPixelSize + cAlphaChannelOffset)); // topLeft
+    ASSERT(alphaWindow.top() == pixels->item(offset - widthMultipliedByPixelSize + cAlphaChannelOffset)); // top
+
     return {
         -topLeft + topRight - 2 * left + 2 * right - bottomLeft + bottomRight,
         -topLeft - 2 * top - topRight + bottomLeft + 2 * bottom + bottomRight
@@ -224,18 +236,27 @@
     };
 }
 
-inline void FELighting::inlineSetPixel(int offset, LightingData& data, LightSource::PaintingData& paintingData, int lightX, int lightY, float factorX, float factorY, IntSize normal2DVector)
+void FELighting::setPixel(int offset, const LightingData& data, const LightSource::PaintingData& paintingData, int x, int y, float factorX, float factorY, IntSize normal2DVector)
 {
-    m_lightSource->updatePaintingData(paintingData, lightX, lightY, static_cast<float>(data.pixels->item(offset + cAlphaChannelOffset)) * data.surfaceScale);
+    setPixelInternal(offset, data, paintingData, x, y, factorX, factorY, normal2DVector, data.pixels->item(offset + cAlphaChannelOffset));
+}
 
+void FELighting::setPixelInternal(int offset, const LightingData& data, const LightSource::PaintingData& paintingData, int x, int y, float factorX, float factorY, IntSize normal2DVector, float alpha)
+{
+    float z = alpha * data.surfaceScale;
+    LightSource::ComputedLightingData lightingData = m_lightSource->computePixelLightingData(paintingData, x, y, z);
+
     float lightStrength;
     if (normal2DVector.isZero()) {
         // Normal vector is (0, 0, 1). This is a quite frequent case.
         if (m_lightingType == FELighting::DiffuseLighting)
-            lightStrength = m_diffuseConstant * paintingData.lightVector.z() / paintingData.lightVectorLength;
+            lightStrength = m_diffuseConstant * lightingData.lightVector.z() / lightingData.lightVectorLength;
         else {
-            FloatPoint3D halfwayVector = paintingData.lightVector;
-            halfwayVector.setZ(halfwayVector.z() + paintingData.lightVectorLength);
+            FloatPoint3D halfwayVector = {
+                lightingData.lightVector.x(),
+                lightingData.lightVector.y(),
+                lightingData.lightVector.z() + lightingData.lightVectorLength
+            };
             float halfwayVectorLength = halfwayVector.length();
             if (m_specularExponent == 1)
                 lightStrength = m_specularConstant * halfwayVector.z() / halfwayVectorLength;
@@ -243,17 +264,21 @@
                 lightStrength = m_specularConstant * powf(halfwayVector.z() / halfwayVectorLength, m_specularExponent);
         }
     } else {
-        FloatPoint3D normalVector;
-        normalVector.setX(factorX * static_cast<float>(normal2DVector.width()) * data.surfaceScale);
-        normalVector.setY(factorY * static_cast<float>(normal2DVector.height()) * data.surfaceScale);
-        normalVector.setZ(1);
+        FloatPoint3D normalVector = {
+            factorX * normal2DVector.width() * data.surfaceScale,
+            factorY * normal2DVector.height() * data.surfaceScale,
+            1.0f
+        };
         float normalVectorLength = normalVector.length();
 
         if (m_lightingType == FELighting::DiffuseLighting)
-            lightStrength = m_diffuseConstant * (normalVector * paintingData.lightVector) / (normalVectorLength * paintingData.lightVectorLength);
+            lightStrength = m_diffuseConstant * (normalVector * lightingData.lightVector) / (normalVectorLength * lightingData.lightVectorLength);
         else {
-            FloatPoint3D halfwayVector = paintingData.lightVector;
-            halfwayVector.setZ(halfwayVector.z() + paintingData.lightVectorLength);
+            FloatPoint3D halfwayVector = {
+                lightingData.lightVector.x(),
+                lightingData.lightVector.y(),
+                lightingData.lightVector.z() + lightingData.lightVectorLength
+            };
             float halfwayVectorLength = halfwayVector.length();
             if (m_specularExponent == 1)
                 lightStrength = m_specularConstant * (normalVector * halfwayVector) / (normalVectorLength * halfwayVectorLength);
@@ -267,22 +292,43 @@
     if (lightStrength < 0)
         lightStrength = 0;
 
-    data.pixels->set(offset, static_cast<unsigned char>(lightStrength * paintingData.colorVector.x()));
-    data.pixels->set(offset + 1, static_cast<unsigned char>(lightStrength * paintingData.colorVector.y()));
-    data.pixels->set(offset + 2, static_cast<unsigned char>(lightStrength * paintingData.colorVector.z()));
+    uint8_t pixelValue[3] = {
+        static_cast<uint8_t>(lightStrength * lightingData.colorVector.x()),
+        static_cast<uint8_t>(lightStrength * lightingData.colorVector.y()),
+        static_cast<uint8_t>(lightStrength * lightingData.colorVector.z())
+    };
+    
+    data.pixels->setRange(pixelValue, 3, offset);
 }
 
-void FELighting::setPixel(int offset, LightingData& data, LightSource::PaintingData& paintingData, int lightX, int lightY, float factorX, float factorY, IntSize normalVector)
+// This appears to read from and write to the same pixel buffer, but it only reads the alpha channel, and writes the non-alpha channels.
+void FELighting::platformApplyGenericPaint(const LightingData& data, const LightSource::PaintingData& paintingData, int startY, int endY)
 {
-    inlineSetPixel(offset, data, paintingData, lightX, lightY, factorX, factorY, normalVector);
-}
+    // Make sure startY is > 0 since we read from the previous row in the loop.
+    ASSERT(startY);
 
-inline void FELighting::platformApplyGenericPaint(LightingData& data, LightSource::PaintingData& paintingData, int startY, int endY)
-{
     for (int y = startY; y < endY; ++y) {
-        int offset = y * data.widthMultipliedByPixelSize + cPixelSize;
+        int rowStartOffset = y * data.widthMultipliedByPixelSize;
+        int previousRowStart = rowStartOffset - data.widthMultipliedByPixelSize;
+        int nextRowStart = rowStartOffset + data.widthMultipliedByPixelSize;
+
+        // alphaWindow is a local cache of alpha values.
+        // Fill the two right columns putting the left edge value in the center column.
+        // For each pixel, we shift each row left then fill the right column.
+        AlphaWindow alphaWindow;
+        alphaWindow.setTop(data.pixels->item(previousRowStart + cAlphaChannelOffset));
+        alphaWindow.setTopRight(data.pixels->item(previousRowStart + cPixelSize + cAlphaChannelOffset));
+
+        alphaWindow.setCenter(data.pixels->item(rowStartOffset + cAlphaChannelOffset));
+        alphaWindow.setRight(data.pixels->item(rowStartOffset + cPixelSize + cAlphaChannelOffset));
+
+        alphaWindow.setBottom(data.pixels->item(nextRowStart + cAlphaChannelOffset));
+        alphaWindow.setBottomRight(data.pixels->item(nextRowStart + cPixelSize + cAlphaChannelOffset));
+
+        int offset = rowStartOffset + cPixelSize;
         for (int x = 1; x < data.widthDecreasedByOne; ++x, offset += cPixelSize) {
-            inlineSetPixel(offset, data, paintingData, x, y, cFactor1div4, cFactor1div4, data.interiorNormal(offset));
+            alphaWindow.shift();
+            setPixelInternal(offset, data, paintingData, x, y, cFactor1div4, cFactor1div4, data.interiorNormal(offset, alphaWindow), alphaWindow.center());
         }
     }
 }
@@ -292,7 +338,7 @@
     parameters->filter->platformApplyGenericPaint(parameters->data, parameters->paintingData, parameters->yStart, parameters->yEnd);
 }
 
-inline void FELighting::platformApplyGeneric(LightingData& data, LightSource::PaintingData& paintingData)
+void FELighting::platformApplyGeneric(const LightingData& data, const LightSource::PaintingData& paintingData)
 {
     int optimalThreadNumber = ((data.widthDecreasedByOne - 1) * (data.heightDecreasedByOne - 1)) / s_minimalRectDimension;
     if (optimalThreadNumber > 1) {
@@ -326,7 +372,7 @@
     platformApplyGenericPaint(data, paintingData, 1, data.heightDecreasedByOne);
 }
 
-inline void FELighting::platformApply(LightingData& data, LightSource::PaintingData& paintingData)
+inline void FELighting::platformApply(const LightingData& data, const LightSource::PaintingData& paintingData)
 {
     // The selection here eventually should happen dynamically on some platforms.
 #if CPU(ARM_NEON) && CPU(ARM_TRADITIONAL) && COMPILER(GCC_OR_CLANG)
@@ -351,7 +397,7 @@
     data.widthMultipliedByPixelSize = width * cPixelSize;
     data.widthDecreasedByOne = width - 1;
     data.heightDecreasedByOne = height - 1;
-    paintingData.colorVector = FloatPoint3D(m_lightingColor.red(), m_lightingColor.green(), m_lightingColor.blue());
+    paintingData.intialLightingData.colorVector = FloatPoint3D(m_lightingColor.red(), m_lightingColor.green(), m_lightingColor.blue());
     m_lightSource->initPaintingData(paintingData);
 
     // Top left.
@@ -374,12 +420,12 @@
         // Top row.
         offset = cPixelSize;
         for (int x = 1; x < data.widthDecreasedByOne; ++x, offset += cPixelSize)
-            inlineSetPixel(offset, data, paintingData, x, 0, cFactor1div3, cFactor1div2, data.topRowNormal(offset));
+            setPixel(offset, data, paintingData, x, 0, cFactor1div3, cFactor1div2, data.topRowNormal(offset));
 
         // Bottom row.
         offset = data.heightDecreasedByOne * data.widthMultipliedByPixelSize + cPixelSize;
         for (int x = 1; x < data.widthDecreasedByOne; ++x, offset += cPixelSize)
-            inlineSetPixel(offset, data, paintingData, x, data.heightDecreasedByOne, cFactor1div3, cFactor1div2, data.bottomRowNormal(offset));
+            setPixel(offset, data, paintingData, x, data.heightDecreasedByOne, cFactor1div3, cFactor1div2, data.bottomRowNormal(offset));
     }
 
     if (height >= 3) {
@@ -386,12 +432,12 @@
         // Left column.
         offset = data.widthMultipliedByPixelSize;
         for (int y = 1; y < data.heightDecreasedByOne; ++y, offset += data.widthMultipliedByPixelSize)
-            inlineSetPixel(offset, data, paintingData, 0, y, cFactor1div2, cFactor1div3, data.leftColumnNormal(offset));
+            setPixel(offset, data, paintingData, 0, y, cFactor1div2, cFactor1div3, data.leftColumnNormal(offset));
 
         // Right column.
         offset = 2 * data.widthMultipliedByPixelSize - cPixelSize;
         for (int y = 1; y < data.heightDecreasedByOne; ++y, offset += data.widthMultipliedByPixelSize)
-            inlineSetPixel(offset, data, paintingData, data.widthDecreasedByOne, y, cFactor1div2, cFactor1div3, data.rightColumnNormal(offset));
+            setPixel(offset, data, paintingData, data.widthDecreasedByOne, y, cFactor1div2, cFactor1div3, data.rightColumnNormal(offset));
     }
 
     if (width >= 3 && height >= 3) {
@@ -405,9 +451,9 @@
             data.pixels->set(i, cOpaqueAlpha);
     } else {
         for (int i = 0; i < lastPixel; i += cPixelSize) {
-            unsigned char a1 = data.pixels->item(i);
-            unsigned char a2 = data.pixels->item(i + 1);
-            unsigned char a3 = data.pixels->item(i + 2);
+            uint8_t a1 = data.pixels->item(i);
+            uint8_t a2 = data.pixels->item(i + 1);
+            uint8_t a3 = data.pixels->item(i + 2);
             // alpha set to set to max(a1, a2, a3)
             data.pixels->set(i + 3, a1 >= a2 ? (a1 >= a3 ? a1 : a3) : (a2 >= a3 ? a2 : a3));
         }

Modified: trunk/Source/WebCore/platform/graphics/filters/FELighting.h (225121 => 225122)


--- trunk/Source/WebCore/platform/graphics/filters/FELighting.h	2017-11-23 21:33:44 UTC (rev 225121)
+++ trunk/Source/WebCore/platform/graphics/filters/FELighting.h	2017-11-23 22:20:09 UTC (rev 225122)
@@ -63,7 +63,41 @@
         DiffuseLighting,
         SpecularLighting
     };
+    
+    struct AlphaWindow {
+        uint8_t alpha[3][3] { };
+        
+        // The implementations are lined up to make comparing indices easier.
+        uint8_t topLeft() const             { return alpha[0][0]; }
+        uint8_t left() const                { return alpha[1][0]; }
+        uint8_t bottomLeft() const          { return alpha[2][0]; }
 
+        uint8_t top() const                 { return alpha[0][1]; }
+        uint8_t center() const              { return alpha[1][1]; }
+        uint8_t bottom() const              { return alpha[2][1]; }
+
+        void setTop(uint8_t value)          { alpha[0][1] = value; }
+        void setCenter(uint8_t value)       { alpha[1][1] = value; }
+        void setBottom(uint8_t value)       { alpha[2][1] = value; }
+
+        void setTopRight(uint8_t value)     { alpha[0][2] = value; }
+        void setRight(uint8_t value)        { alpha[1][2] = value; }
+        void setBottomRight(uint8_t value)  { alpha[2][2] = value; }
+
+        static void shiftRow(uint8_t alpha[3])
+        {
+            alpha[0] = alpha[1];
+            alpha[1] = alpha[2];
+        }
+        
+        void shift()
+        {
+            shiftRow(alpha[0]);
+            shiftRow(alpha[1]);
+            shiftRow(alpha[2]);
+        }
+    };
+
     struct LightingData {
         // This structure contains only read-only (SMP safe) data
         Uint8ClampedArray* pixels;
@@ -76,7 +110,7 @@
         inline IntSize topRowNormal(int offset) const;
         inline IntSize topRightNormal(int offset) const;
         inline IntSize leftColumnNormal(int offset) const;
-        inline IntSize interiorNormal(int offset) const;
+        inline IntSize interiorNormal(int offset, AlphaWindow&) const;
         inline IntSize rightColumnNormal(int offset) const;
         inline IntSize bottomLeftNormal(int offset) const;
         inline IntSize bottomRowNormal(int offset) const;
@@ -100,23 +134,20 @@
     FELighting(Filter&, LightingType, const Color&, float, float, float, float, float, float, Ref<LightSource>&&);
 
     bool drawLighting(Uint8ClampedArray*, int, int);
-    inline void inlineSetPixel(int offset, LightingData&, LightSource::PaintingData&,
-        int lightX, int lightY, float factorX, float factorY, IntSize normalVector);
 
-    // Not worth to inline every occurence of setPixel.
-    void setPixel(int offset, LightingData&, LightSource::PaintingData&,
-        int lightX, int lightY, float factorX, float factorY, IntSize normalVector);
+    void setPixel(int offset, const LightingData&, const LightSource::PaintingData&, int x, int y, float factorX, float factorY, IntSize normalVector);
+    void setPixelInternal(int offset, const LightingData&, const LightSource::PaintingData&, int x, int y, float factorX, float factorY, IntSize normalVector, float alpha);
 
     void platformApplySoftware() override;
 
-    inline void platformApply(LightingData&, LightSource::PaintingData&);
+    void platformApply(const LightingData&, const LightSource::PaintingData&);
 
-    inline void platformApplyGenericPaint(LightingData&, LightSource::PaintingData&, int startX, int startY);
-    inline void platformApplyGeneric(LightingData&, LightSource::PaintingData&);
+    void platformApplyGenericPaint(const LightingData&, const LightSource::PaintingData&, int startX, int startY);
+    void platformApplyGeneric(const LightingData&, const LightSource::PaintingData&);
 
 #if CPU(ARM_NEON) && CPU(ARM_TRADITIONAL) && COMPILER(GCC_OR_CLANG)
     static int getPowerCoefficients(float exponent);
-    inline void platformApplyNeon(LightingData&, LightSource::PaintingData&);
+    inline void platformApplyNeon(const LightingData&, const LightSource::PaintingData&);
 #endif
 
     LightingType m_lightingType;

Modified: trunk/Source/WebCore/platform/graphics/filters/LightSource.h (225121 => 225122)


--- trunk/Source/WebCore/platform/graphics/filters/LightSource.h	2017-11-23 21:33:44 UTC (rev 225121)
+++ trunk/Source/WebCore/platform/graphics/filters/LightSource.h	2017-11-23 22:20:09 UTC (rev 225122)
@@ -21,8 +21,7 @@
  * Boston, MA 02110-1301, USA.
  */
 
-#ifndef LightSource_h
-#define LightSource_h
+#pragma once
 
 #include "FloatPoint3D.h"
 #include <wtf/RefCounted.h>
@@ -41,20 +40,15 @@
 
 class LightSource : public RefCounted<LightSource> {
 public:
-
-    // Light vectors must be calculated for every pixel during
-    // painting. It is expensive to pass all these arguments to
-    // a frequently called function, especially because not all
-    // light sources require all of them. Instead, we just pass
-    // a reference to the following structure
-    struct PaintingData {
-        // SVGFELighting also use them
+    struct ComputedLightingData {
         FloatPoint3D lightVector;
         FloatPoint3D colorVector;
         float lightVectorLength;
-        // Private members
+    };
+
+    struct PaintingData {
+        ComputedLightingData intialLightingData;
         FloatPoint3D directionVector;
-        FloatPoint3D privateColorVector;
         float coneCutOffLimit;
         float coneFullLight;
         int specularExponent;
@@ -72,7 +66,7 @@
     virtual void initPaintingData(PaintingData&) = 0;
     // z is a float number, since it is the alpha value scaled by a user
     // specified "surfaceScale" constant, which type is <number> in the SVG standard
-    virtual void updatePaintingData(PaintingData&, int x, int y, float z) = 0;
+    virtual ComputedLightingData computePixelLightingData(const PaintingData&, int x, int y, float z) const = 0;
 
     virtual bool setAzimuth(float) { return false; }
     virtual bool setElevation(float) { return false; }
@@ -91,4 +85,7 @@
 
 } // namespace WebCore
 
-#endif // LightSource_h
+#define SPECIALIZE_TYPE_TRAITS_LIGHTSOURCE(ClassName, Type) \
+SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::ClassName) \
+    static bool isType(const WebCore::LightSource& source) { return source.type() == WebCore::Type; } \
+SPECIALIZE_TYPE_TRAITS_END()

Modified: trunk/Source/WebCore/platform/graphics/filters/PointLightSource.cpp (225121 => 225122)


--- trunk/Source/WebCore/platform/graphics/filters/PointLightSource.cpp	2017-11-23 21:33:44 UTC (rev 225121)
+++ trunk/Source/WebCore/platform/graphics/filters/PointLightSource.cpp	2017-11-23 22:20:09 UTC (rev 225122)
@@ -39,12 +39,15 @@
 {
 }
 
-void PointLightSource::updatePaintingData(PaintingData& paintingData, int x, int y, float z)
+LightSource::ComputedLightingData PointLightSource::computePixelLightingData(const PaintingData&, int x, int y, float z) const
 {
-    paintingData.lightVector.setX(m_position.x() - x);
-    paintingData.lightVector.setY(m_position.y() - y);
-    paintingData.lightVector.setZ(m_position.z() - z);
-    paintingData.lightVectorLength = paintingData.lightVector.length();
+    FloatPoint3D lightVector = {
+        m_position.x() - x,
+        m_position.y() - y,
+        m_position.z() - z
+    };
+
+    return { lightVector, { }, lightVector.length() };
 }
 
 bool PointLightSource::setX(float x)

Modified: trunk/Source/WebCore/platform/graphics/filters/PointLightSource.h (225121 => 225122)


--- trunk/Source/WebCore/platform/graphics/filters/PointLightSource.h	2017-11-23 21:33:44 UTC (rev 225121)
+++ trunk/Source/WebCore/platform/graphics/filters/PointLightSource.h	2017-11-23 22:20:09 UTC (rev 225122)
@@ -20,8 +20,7 @@
  * Boston, MA 02110-1301, USA.
  */
 
-#ifndef PointLightSource_h
-#define PointLightSource_h
+#pragma once
 
 #include "LightSource.h"
 #include <wtf/Ref.h>
@@ -41,7 +40,7 @@
     bool setZ(float) override;
 
     void initPaintingData(PaintingData&) override;
-    void updatePaintingData(PaintingData&, int x, int y, float z) override;
+    ComputedLightingData computePixelLightingData(const PaintingData&, int x, int y, float z) const final;
 
     WTF::TextStream& externalRepresentation(WTF::TextStream&) const override;
 
@@ -57,4 +56,4 @@
 
 } // namespace WebCore
 
-#endif // PointLightSource_h
+SPECIALIZE_TYPE_TRAITS_LIGHTSOURCE(PointLightSource, LS_POINT)

Modified: trunk/Source/WebCore/platform/graphics/filters/SpotLightSource.cpp (225121 => 225122)


--- trunk/Source/WebCore/platform/graphics/filters/SpotLightSource.cpp	2017-11-23 21:33:44 UTC (rev 225121)
+++ trunk/Source/WebCore/platform/graphics/filters/SpotLightSource.cpp	2017-11-23 22:20:09 UTC (rev 225122)
@@ -42,10 +42,7 @@
 
 void SpotLightSource::initPaintingData(PaintingData& paintingData)
 {
-    paintingData.privateColorVector = paintingData.colorVector;
-    paintingData.directionVector.setX(m_direction.x() - m_position.x());
-    paintingData.directionVector.setY(m_direction.y() - m_position.y());
-    paintingData.directionVector.setZ(m_direction.z() - m_position.z());
+    paintingData.directionVector = m_direction - m_position;
     paintingData.directionVector.normalize();
 
     if (!m_limitingConeAngle) {
@@ -70,20 +67,19 @@
         paintingData.specularExponent = 2;
 }
 
-void SpotLightSource::updatePaintingData(PaintingData& paintingData, int x, int y, float z)
+LightSource::ComputedLightingData SpotLightSource::computePixelLightingData(const PaintingData& paintingData, int x, int y, float z) const
 {
-    paintingData.lightVector.setX(m_position.x() - x);
-    paintingData.lightVector.setY(m_position.y() - y);
-    paintingData.lightVector.setZ(m_position.z() - z);
-    paintingData.lightVectorLength = paintingData.lightVector.length();
+    FloatPoint3D lightVector = {
+        m_position.x() - x,
+        m_position.y() - y,
+        m_position.z() - z
+    };
+    float lightVectorLength = lightVector.length();
 
-    float cosineOfAngle = (paintingData.lightVector * paintingData.directionVector) / paintingData.lightVectorLength;
+    float cosineOfAngle = (lightVector * paintingData.directionVector) / lightVectorLength;
     if (cosineOfAngle > paintingData.coneCutOffLimit) {
         // No light is produced, scanlines are not updated
-        paintingData.colorVector.setX(0.0f);
-        paintingData.colorVector.setY(0.0f);
-        paintingData.colorVector.setZ(0.0f);
-        return;
+        return { lightVector, { }, lightVectorLength };
     }
 
     // Set the color of the pixel
@@ -106,9 +102,11 @@
     if (lightStrength > 1.0f)
         lightStrength = 1.0f;
 
-    paintingData.colorVector.setX(paintingData.privateColorVector.x() * lightStrength);
-    paintingData.colorVector.setY(paintingData.privateColorVector.y() * lightStrength);
-    paintingData.colorVector.setZ(paintingData.privateColorVector.z() * lightStrength);
+    return {
+        lightVector,
+        paintingData.intialLightingData.colorVector * lightStrength,
+        lightVectorLength
+    };
 }
 
 bool SpotLightSource::setX(float x)

Modified: trunk/Source/WebCore/platform/graphics/filters/SpotLightSource.h (225121 => 225122)


--- trunk/Source/WebCore/platform/graphics/filters/SpotLightSource.h	2017-11-23 21:33:44 UTC (rev 225121)
+++ trunk/Source/WebCore/platform/graphics/filters/SpotLightSource.h	2017-11-23 22:20:09 UTC (rev 225122)
@@ -20,8 +20,7 @@
  * Boston, MA 02110-1301, USA.
  */
 
-#ifndef SpotLightSource_h
-#define SpotLightSource_h
+#pragma once
 
 #include "LightSource.h"
 #include <wtf/Ref.h>
@@ -52,7 +51,7 @@
     bool setLimitingConeAngle(float) override;
 
     void initPaintingData(PaintingData&) override;
-    void updatePaintingData(PaintingData&, int x, int y, float z) override;
+    ComputedLightingData computePixelLightingData(const PaintingData&, int x, int y, float z) const final;
 
     WTF::TextStream& externalRepresentation(WTF::TextStream&) const override;
 
@@ -76,4 +75,4 @@
 
 } // namespace WebCore
 
-#endif // SpotLightSource_h
+SPECIALIZE_TYPE_TRAITS_LIGHTSOURCE(SpotLightSource, LS_SPOT)
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to