[SCM] WebKit Debian packaging branch, debian/experimental, updated. upstream/1.3.3-9427-gc2be6fc

zherczeg at webkit.org zherczeg at webkit.org
Wed Dec 22 15:25:54 UTC 2010


The following commit has been merged in the debian/experimental branch:
commit 0b03670f6f3a9124ea7ed72d94f5784125e1353a
Author: zherczeg at webkit.org <zherczeg at webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Wed Nov 3 08:36:22 2010 +0000

    SVG FELighting performance issues
    https://bugs.webkit.org/show_bug.cgi?id=48212
    
    Reviewed by Dirk Schulze.
    
    This patch speeds-up FELighting filter painting by 40%
    It reduces the number of floating point operations and
    empolys faster pixel manipulation (both for read and
    write). Furthermore the length() member of FloatPoint3D
    is made inline to speed up vector length calculations.
    
    The lighting filter pixels tests are cover this patch.
    
    * platform/graphics/FloatPoint3D.cpp:
    * platform/graphics/FloatPoint3D.h:
    (WebCore::FloatPoint3D::length):
    * platform/graphics/filters/FELighting.cpp:
    (WebCore::FELighting::LightingData::topLeft):
    (WebCore::FELighting::LightingData::topRow):
    (WebCore::FELighting::LightingData::topRight):
    (WebCore::FELighting::LightingData::leftColumn):
    (WebCore::FELighting::LightingData::interior):
    (WebCore::FELighting::LightingData::rightColumn):
    (WebCore::FELighting::LightingData::bottomLeft):
    (WebCore::FELighting::LightingData::bottomRow):
    (WebCore::FELighting::LightingData::bottomRight):
    (WebCore::FELighting::inlineSetPixel):
    (WebCore::FELighting::setPixel):
    (WebCore::FELighting::drawLighting):
    (WebCore::FELighting::apply):
    * platform/graphics/filters/FELighting.h:
    * platform/graphics/filters/LightSource.cpp:
    (WebCore::PointLightSource::updatePaintingData):
    (WebCore::SpotLightSource::updatePaintingData):
    (WebCore::DistantLightSource::initPaintingData):
    * platform/graphics/filters/LightSource.h:
    
    
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@71222 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index e259a7d..d30ca7c 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -1,3 +1,42 @@
+2010-11-03  Zoltan Herczeg  <zherczeg at webkit.org>
+
+        Reviewed by Dirk Schulze.
+
+        SVG FELighting performance issues
+        https://bugs.webkit.org/show_bug.cgi?id=48212
+
+        This patch speeds-up FELighting filter painting by 40%
+        It reduces the number of floating point operations and
+        empolys faster pixel manipulation (both for read and
+        write). Furthermore the length() member of FloatPoint3D
+        is made inline to speed up vector length calculations.
+
+        The lighting filter pixels tests are cover this patch.
+
+        * platform/graphics/FloatPoint3D.cpp:
+        * platform/graphics/FloatPoint3D.h:
+        (WebCore::FloatPoint3D::length):
+        * platform/graphics/filters/FELighting.cpp:
+        (WebCore::FELighting::LightingData::topLeft):
+        (WebCore::FELighting::LightingData::topRow):
+        (WebCore::FELighting::LightingData::topRight):
+        (WebCore::FELighting::LightingData::leftColumn):
+        (WebCore::FELighting::LightingData::interior):
+        (WebCore::FELighting::LightingData::rightColumn):
+        (WebCore::FELighting::LightingData::bottomLeft):
+        (WebCore::FELighting::LightingData::bottomRow):
+        (WebCore::FELighting::LightingData::bottomRight):
+        (WebCore::FELighting::inlineSetPixel):
+        (WebCore::FELighting::setPixel):
+        (WebCore::FELighting::drawLighting):
+        (WebCore::FELighting::apply):
+        * platform/graphics/filters/FELighting.h:
+        * platform/graphics/filters/LightSource.cpp:
+        (WebCore::PointLightSource::updatePaintingData):
+        (WebCore::SpotLightSource::updatePaintingData):
+        (WebCore::DistantLightSource::initPaintingData):
+        * platform/graphics/filters/LightSource.h:
+
 2010-11-03  Daniel Bates  <dbates at rim.com>
 
         Reviewed by Adam Barth.
diff --git a/WebCore/platform/graphics/FloatPoint3D.cpp b/WebCore/platform/graphics/FloatPoint3D.cpp
index bb05e7f..ed1816b 100644
--- a/WebCore/platform/graphics/FloatPoint3D.cpp
+++ b/WebCore/platform/graphics/FloatPoint3D.cpp
@@ -38,10 +38,5 @@ void FloatPoint3D::normalize()
     }
 }
 
-float FloatPoint3D::length() const
-{
-    return sqrtf(lengthSquared());
-}
-
 } // namespace WebCore
 
diff --git a/WebCore/platform/graphics/FloatPoint3D.h b/WebCore/platform/graphics/FloatPoint3D.h
index 9ee548d..b6cbaa8 100644
--- a/WebCore/platform/graphics/FloatPoint3D.h
+++ b/WebCore/platform/graphics/FloatPoint3D.h
@@ -113,8 +113,8 @@ public:
         return result;
     }
 
-    float length() const;
     float lengthSquared() const { return this->dot(*this); }
+    float length() const { return sqrtf(lengthSquared()); }
 
 private:
     float m_x;
diff --git a/WebCore/platform/graphics/filters/FELighting.cpp b/WebCore/platform/graphics/filters/FELighting.cpp
index e1df580..803b9c1 100644
--- a/WebCore/platform/graphics/filters/FELighting.cpp
+++ b/WebCore/platform/graphics/filters/FELighting.cpp
@@ -54,85 +54,182 @@ FELighting::FELighting(LightingType lightingType, const Color& lightingColor, fl
 const static int cPixelSize = 4;
 const static int cAlphaChannelOffset = 3;
 const static unsigned char cOpaqueAlpha = static_cast<unsigned char>(0xff);
+const static float cFactor1div2 = -1 / 2.f;
+const static float cFactor1div3 = -1 / 3.f;
+const static float cFactor1div4 = -1 / 4.f;
+const static float cFactor2div3 = -2 / 3.f;
 
-ALWAYS_INLINE int FELighting::LightingData::upLeftPixelValue()
+// << 1 is signed multiply by 2
+inline void FELighting::LightingData::topLeft(int offset, IntPoint& normalVector)
 {
-    return static_cast<int>(pixels->get(offset - widthMultipliedByPixelSize - cPixelSize + cAlphaChannelOffset));
+    int center = static_cast<int>(pixels->get(offset + cAlphaChannelOffset));
+    int right = static_cast<int>(pixels->get(offset + cPixelSize + cAlphaChannelOffset));
+    offset += widthMultipliedByPixelSize;
+    int bottom = static_cast<int>(pixels->get(offset + cAlphaChannelOffset));
+    int bottomRight = static_cast<int>(pixels->get(offset + cPixelSize + cAlphaChannelOffset));
+    normalVector.setX(-(center << 1) + (right << 1) - bottom + bottomRight);
+    normalVector.setY(-(center << 1) - right + (bottom << 1) + bottomRight);
 }
 
-ALWAYS_INLINE int FELighting::LightingData::upPixelValue()
+inline void FELighting::LightingData::topRow(int offset, IntPoint& normalVector)
 {
-    return static_cast<int>(pixels->get(offset - widthMultipliedByPixelSize + cAlphaChannelOffset));
+    int left = static_cast<int>(pixels->get(offset - cPixelSize + cAlphaChannelOffset));
+    int center = static_cast<int>(pixels->get(offset + cAlphaChannelOffset));
+    int right = static_cast<int>(pixels->get(offset + cPixelSize + cAlphaChannelOffset));
+    offset += widthMultipliedByPixelSize;
+    int bottomLeft = static_cast<int>(pixels->get(offset - cPixelSize + cAlphaChannelOffset));
+    int bottom = static_cast<int>(pixels->get(offset + cAlphaChannelOffset));
+    int bottomRight = static_cast<int>(pixels->get(offset + cPixelSize + cAlphaChannelOffset));
+    normalVector.setX(-(left << 1) + (right << 1) - bottomLeft + bottomRight);
+    normalVector.setY(-left - (center << 1) - right + bottomLeft + (bottom << 1) + bottomRight);
 }
 
-ALWAYS_INLINE int FELighting::LightingData::upRightPixelValue()
+inline void FELighting::LightingData::topRight(int offset, IntPoint& normalVector)
 {
-    return static_cast<int>(pixels->get(offset - widthMultipliedByPixelSize + cPixelSize + cAlphaChannelOffset));
+    int left = static_cast<int>(pixels->get(offset - cPixelSize + cAlphaChannelOffset));
+    int center = static_cast<int>(pixels->get(offset + cAlphaChannelOffset));
+    offset += widthMultipliedByPixelSize;
+    int bottomLeft = static_cast<int>(pixels->get(offset - cPixelSize + cAlphaChannelOffset));
+    int bottom = static_cast<int>(pixels->get(offset + cAlphaChannelOffset));
+    normalVector.setX(-(left << 1) + (center << 1) - bottomLeft + bottom);
+    normalVector.setY(-left - (center << 1) + bottomLeft + (bottom << 1));
 }
 
-ALWAYS_INLINE int FELighting::LightingData::leftPixelValue()
+inline void FELighting::LightingData::leftColumn(int offset, IntPoint& normalVector)
 {
-    return static_cast<int>(pixels->get(offset - cPixelSize + cAlphaChannelOffset));
+    int center = static_cast<int>(pixels->get(offset + cAlphaChannelOffset));
+    int right = static_cast<int>(pixels->get(offset + cPixelSize + cAlphaChannelOffset));
+    offset -= widthMultipliedByPixelSize;
+    int top = static_cast<int>(pixels->get(offset + cAlphaChannelOffset));
+    int topRight = static_cast<int>(pixels->get(offset + cPixelSize + cAlphaChannelOffset));
+    offset += widthMultipliedByPixelSize << 1;
+    int bottom = static_cast<int>(pixels->get(offset + cAlphaChannelOffset));
+    int bottomRight = static_cast<int>(pixels->get(offset + cPixelSize + cAlphaChannelOffset));
+    normalVector.setX(-top + topRight - (center << 1) + (right << 1) - bottom + bottomRight);
+    normalVector.setY(-(top << 1) - topRight + (bottom << 1) + bottomRight);
 }
 
-ALWAYS_INLINE int FELighting::LightingData::centerPixelValue()
+inline void FELighting::LightingData::interior(int offset, IntPoint& normalVector)
 {
-    return static_cast<int>(pixels->get(offset + cAlphaChannelOffset));
+    int left = static_cast<int>(pixels->get(offset - cPixelSize + cAlphaChannelOffset));
+    int right = static_cast<int>(pixels->get(offset + cPixelSize + cAlphaChannelOffset));
+    offset -= widthMultipliedByPixelSize;
+    int topLeft = static_cast<int>(pixels->get(offset - cPixelSize + cAlphaChannelOffset));
+    int top = static_cast<int>(pixels->get(offset + cAlphaChannelOffset));
+    int topRight = static_cast<int>(pixels->get(offset + cPixelSize + cAlphaChannelOffset));
+    offset += widthMultipliedByPixelSize << 1;
+    int bottomLeft = static_cast<int>(pixels->get(offset - cPixelSize + cAlphaChannelOffset));
+    int bottom = static_cast<int>(pixels->get(offset + cAlphaChannelOffset));
+    int bottomRight = static_cast<int>(pixels->get(offset + cPixelSize + cAlphaChannelOffset));
+    normalVector.setX(-topLeft + topRight - (left << 1) + (right << 1) - bottomLeft + bottomRight);
+    normalVector.setY(-topLeft - (top << 1) - topRight + bottomLeft + (bottom << 1) + bottomRight);
 }
 
-ALWAYS_INLINE int FELighting::LightingData::rightPixelValue()
+inline void FELighting::LightingData::rightColumn(int offset, IntPoint& normalVector)
 {
-    return static_cast<int>(pixels->get(offset + cPixelSize + cAlphaChannelOffset));
+    int left = static_cast<int>(pixels->get(offset - cPixelSize + cAlphaChannelOffset));
+    int center = static_cast<int>(pixels->get(offset + cAlphaChannelOffset));
+    offset -= widthMultipliedByPixelSize;
+    int topLeft = static_cast<int>(pixels->get(offset - cPixelSize + cAlphaChannelOffset));
+    int top = static_cast<int>(pixels->get(offset + cAlphaChannelOffset));
+    offset += widthMultipliedByPixelSize << 1;
+    int bottomLeft = static_cast<int>(pixels->get(offset - cPixelSize + cAlphaChannelOffset));
+    int bottom = static_cast<int>(pixels->get(offset + cAlphaChannelOffset));
+    normalVector.setX(-topLeft + top - (left << 1) + (center << 1) - bottomLeft + bottom);
+    normalVector.setY(-topLeft - (top << 1) + bottomLeft + (bottom << 1));
 }
 
-ALWAYS_INLINE int FELighting::LightingData::downLeftPixelValue()
+inline void FELighting::LightingData::bottomLeft(int offset, IntPoint& normalVector)
 {
-    return static_cast<int>(pixels->get(offset + widthMultipliedByPixelSize - cPixelSize + cAlphaChannelOffset));
+    int center = static_cast<int>(pixels->get(offset + cAlphaChannelOffset));
+    int right = static_cast<int>(pixels->get(offset + cPixelSize + cAlphaChannelOffset));
+    offset -= widthMultipliedByPixelSize;
+    int top = static_cast<int>(pixels->get(offset + cAlphaChannelOffset));
+    int topRight = static_cast<int>(pixels->get(offset + cPixelSize + cAlphaChannelOffset));
+    normalVector.setX(-top + topRight - (center << 1) + (right << 1));
+    normalVector.setY(-(top << 1) - topRight + (center << 1) + right);
 }
 
-ALWAYS_INLINE int FELighting::LightingData::downPixelValue()
+inline void FELighting::LightingData::bottomRow(int offset, IntPoint& normalVector)
 {
-    return static_cast<int>(pixels->get(offset + widthMultipliedByPixelSize + cAlphaChannelOffset));
+    int left = static_cast<int>(pixels->get(offset - cPixelSize + cAlphaChannelOffset));
+    int center = static_cast<int>(pixels->get(offset + cAlphaChannelOffset));
+    int right = static_cast<int>(pixels->get(offset + cPixelSize + cAlphaChannelOffset));
+    offset -= widthMultipliedByPixelSize;
+    int topLeft = static_cast<int>(pixels->get(offset - cPixelSize + cAlphaChannelOffset));
+    int top = static_cast<int>(pixels->get(offset + cAlphaChannelOffset));
+    int topRight = static_cast<int>(pixels->get(offset + cPixelSize + cAlphaChannelOffset));
+    normalVector.setX(-topLeft + topRight - (left << 1) + (right << 1));
+    normalVector.setY(-topLeft - (top << 1) - topRight + left + (center << 1) + right);
 }
 
-ALWAYS_INLINE int FELighting::LightingData::downRightPixelValue()
+inline void FELighting::LightingData::bottomRight(int offset, IntPoint& normalVector)
 {
-    return static_cast<int>(pixels->get(offset + widthMultipliedByPixelSize + cPixelSize + cAlphaChannelOffset));
+    int left = static_cast<int>(pixels->get(offset - cPixelSize + cAlphaChannelOffset));
+    int center = static_cast<int>(pixels->get(offset + cAlphaChannelOffset));
+    offset -= widthMultipliedByPixelSize;
+    int topLeft = static_cast<int>(pixels->get(offset - cPixelSize + cAlphaChannelOffset));
+    int top = static_cast<int>(pixels->get(offset + cAlphaChannelOffset));
+    normalVector.setX(-topLeft + top - (left << 1) + (center << 1));
+    normalVector.setY(-topLeft - (top << 1) + left + (center << 1));
 }
 
-ALWAYS_INLINE void FELighting::setPixel(LightingData& data, LightSource::PaintingData& paintingData,
-    int lightX, int lightY, float factorX, int normalX, float factorY, int normalY)
+inline void FELighting::inlineSetPixel(int offset, LightingData& data, LightSource::PaintingData& paintingData,
+                                       int lightX, int lightY, float factorX, float factorY, IntPoint& normal2DVector)
 {
-    m_lightSource->updatePaintingData(paintingData, lightX, lightY, static_cast<float>(data.pixels->get(data.offset + 3)) * data.surfaceScale);
-
-    data.normalVector.setX(factorX * static_cast<float>(normalX) * data.surfaceScale);
-    data.normalVector.setY(factorY * static_cast<float>(normalY) * data.surfaceScale);
-    data.normalVector.setZ(1.0f);
-    data.normalVector.normalize();
-
-    if (m_lightingType == FELighting::DiffuseLighting)
-        data.lightStrength = m_diffuseConstant * (data.normalVector * paintingData.lightVector);
-    else {
-        FloatPoint3D halfwayVector = paintingData.lightVector;
-        halfwayVector.setZ(halfwayVector.z() + 1.0f);
-        halfwayVector.normalize();
-        if (m_specularExponent == 1.0f)
-            data.lightStrength = m_specularConstant * (data.normalVector * halfwayVector);
-        else
-            data.lightStrength = m_specularConstant * powf(data.normalVector * halfwayVector, m_specularExponent);
+    m_lightSource->updatePaintingData(paintingData, lightX, lightY, static_cast<float>(data.pixels->get(offset + cAlphaChannelOffset)) * data.surfaceScale);
+
+    float lightStrength;
+    if (!normal2DVector.x() && !normal2DVector.y()) {
+        // 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;
+        else {
+            FloatPoint3D halfwayVector = paintingData.lightVector;
+            halfwayVector.setZ(halfwayVector.z() + paintingData.lightVectorLength);
+            float halfwayVectorLength = halfwayVector.length();
+            if (m_specularExponent == 1)
+                lightStrength = m_specularConstant * halfwayVector.z() / halfwayVectorLength;
+            else
+                lightStrength = m_specularConstant * powf(halfwayVector.z() / halfwayVectorLength, m_specularExponent);
+        }
+    } else {
+        FloatPoint3D normalVector;
+        normalVector.setX(factorX * static_cast<float>(normal2DVector.x()) * data.surfaceScale);
+        normalVector.setY(factorY * static_cast<float>(normal2DVector.y()) * data.surfaceScale);
+        normalVector.setZ(1);
+        float normalVectorLength = normalVector.length();
+
+        if (m_lightingType == FELighting::DiffuseLighting)
+            lightStrength = m_diffuseConstant * (normalVector * paintingData.lightVector) / (normalVectorLength * paintingData.lightVectorLength);
+        else {
+            FloatPoint3D halfwayVector = paintingData.lightVector;
+            halfwayVector.setZ(halfwayVector.z() + paintingData.lightVectorLength);
+            float halfwayVectorLength = halfwayVector.length();
+            if (m_specularExponent == 1)
+                lightStrength = m_specularConstant * (normalVector * halfwayVector) / (normalVectorLength * halfwayVectorLength);
+            else
+                lightStrength = m_specularConstant * powf((normalVector * halfwayVector) / (normalVectorLength * halfwayVectorLength), m_specularExponent);
+        }
     }
 
-    if (data.lightStrength > 1.0f)
-        data.lightStrength = 1.0f;
-    if (data.lightStrength < 0.0f)
-        data.lightStrength = 0.0f;
+    if (lightStrength > 1)
+        lightStrength = 1;
+    if (lightStrength < 0)
+        lightStrength = 0;
 
-    data.pixels->set(data.offset, static_cast<unsigned char>(data.lightStrength * paintingData.colorVector.x()));
-    data.pixels->set(data.offset + 1, static_cast<unsigned char>(data.lightStrength * paintingData.colorVector.y()));
-    data.pixels->set(data.offset + 2, static_cast<unsigned char>(data.lightStrength * paintingData.colorVector.z()));
+    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()));
+}
+
+void FELighting::setPixel(int offset, LightingData& data, LightSource::PaintingData& paintingData,
+                          int lightX, int lightY, float factorX, float factorY, IntPoint& normalVector)
+{
+    inlineSetPixel(offset, data, paintingData, lightX, lightY, factorX, factorY, normalVector);
 }
 
-bool FELighting::drawLighting(CanvasPixelArray* pixels, int width, int height)
+bool FELighting::drawLighting(ByteArray* pixels, int width, int height)
 {
     LightSource::PaintingData paintingData;
     LightingData data;
@@ -154,81 +251,73 @@ bool FELighting::drawLighting(CanvasPixelArray* pixels, int width, int height)
     m_lightSource->initPaintingData(paintingData);
 
     // Top/Left corner
-    data.offset = 0;
-    setPixel(data, paintingData, 0, 0,
-        -2.0f / 3.0f, -2 * data.centerPixelValue() + 2 * data.rightPixelValue() - data.downPixelValue() + data.downRightPixelValue(),
-        -2.0f / 3.0f, -2 * data.centerPixelValue() - data.rightPixelValue() + 2 * data.downPixelValue() + data.downRightPixelValue());
+    IntPoint normalVector;
+    int offset = 0;
+    data.topLeft(offset, normalVector);
+    setPixel(offset, data, paintingData, 0, 0, cFactor2div3, cFactor2div3, normalVector);
 
     // Top/Right pixel
-    data.offset = data.widthMultipliedByPixelSize - cPixelSize;
-    setPixel(data, paintingData, data.widthDecreasedByOne, 0,
-        -2.0f / 3.0f, -2 * data.leftPixelValue() + 2 * data.centerPixelValue() - data.downLeftPixelValue() + data.downPixelValue(),
-        -2.0f / 3.0f, -data.leftPixelValue() - 2 * data.centerPixelValue() + data.downLeftPixelValue() + 2 * data.downPixelValue());
+    offset = data.widthMultipliedByPixelSize - cPixelSize;
+    data.topRight(offset, normalVector);
+    setPixel(offset, data, paintingData, data.widthDecreasedByOne, 0, cFactor2div3, cFactor2div3, normalVector);
 
     // Bottom/Left pixel
-    data.offset = data.heightDecreasedByOne * data.widthMultipliedByPixelSize;
-    setPixel(data, paintingData, 0, data.heightDecreasedByOne,
-        -2.0f / 3.0f, -data.upPixelValue() + data.upRightPixelValue() - 2 * data.centerPixelValue() + 2 * data.rightPixelValue(),
-        -2.0f / 3.0f, -2 * data.upPixelValue() - data.upRightPixelValue() + 2 * data.centerPixelValue() + data.rightPixelValue());
+    offset = data.heightDecreasedByOne * data.widthMultipliedByPixelSize;
+    data.bottomLeft(offset, normalVector);
+    setPixel(offset, data, paintingData, 0, data.heightDecreasedByOne, cFactor2div3, cFactor2div3, normalVector);
 
     // Bottom/Right pixel
-    data.offset = height * data.widthMultipliedByPixelSize - cPixelSize;
-    setPixel(data, paintingData, data.widthDecreasedByOne, data.heightDecreasedByOne,
-        -2.0f / 3.0f, -data.upLeftPixelValue() + data.upPixelValue() - 2 * data.leftPixelValue() + 2 * data.centerPixelValue(),
-        -2.0f / 3.0f, -data.upLeftPixelValue() - 2 * data.upPixelValue() + data.leftPixelValue() + 2 * data.centerPixelValue());
+    offset = height * data.widthMultipliedByPixelSize - cPixelSize;
+    data.bottomRight(offset, normalVector);
+    setPixel(offset, data, paintingData, data.widthDecreasedByOne, data.heightDecreasedByOne, cFactor2div3, cFactor2div3, normalVector);
 
     if (width >= 3) {
-        // Top line
-        data.offset = cPixelSize;
-        for (int x = 1; x < data.widthDecreasedByOne; ++x, data.offset += cPixelSize) {
-            setPixel(data, paintingData, x, 0,
-                -1.0f / 3.0f, -2 * data.leftPixelValue() + 2 * data.rightPixelValue() - data.downLeftPixelValue() + data.downRightPixelValue(),
-                -1.0f / 2.0f, -data.leftPixelValue() - 2 * data.centerPixelValue() - data.rightPixelValue() + data.downLeftPixelValue() + 2 * data.downPixelValue() + data.downRightPixelValue());
+        // Top row
+        offset = cPixelSize;
+        for (int x = 1; x < data.widthDecreasedByOne; ++x, offset += cPixelSize) {
+            data.topRow(offset, normalVector);
+            inlineSetPixel(offset, data, paintingData, x, 0, cFactor1div3, cFactor1div2, normalVector);
         }
-        // Bottom line
-        data.offset = data.heightDecreasedByOne * data.widthMultipliedByPixelSize + cPixelSize;
-        for (int x = 1; x < data.widthDecreasedByOne; ++x, data.offset += cPixelSize) {
-            setPixel(data, paintingData, x, data.heightDecreasedByOne,
-                -1.0f / 3.0f, -data.upLeftPixelValue() + data.upRightPixelValue() - 2 * data.leftPixelValue() + 2 * data.rightPixelValue(),
-                -1.0f / 2.0f, -data.upLeftPixelValue() - 2 * data.upPixelValue() - data.upRightPixelValue() + data.leftPixelValue() + 2 * data.centerPixelValue() + data.rightPixelValue());
+        // Bottom row
+        offset = data.heightDecreasedByOne * data.widthMultipliedByPixelSize + cPixelSize;
+        for (int x = 1; x < data.widthDecreasedByOne; ++x, offset += cPixelSize) {
+            data.bottomRow(offset, normalVector);
+            inlineSetPixel(offset, data, paintingData, x, data.heightDecreasedByOne, cFactor1div3, cFactor1div2, normalVector);
         }
     }
 
     if (height >= 3) {
-        // Left line
-        data.offset = data.widthMultipliedByPixelSize;
-        for (int y = 1; y < data.heightDecreasedByOne; ++y, data.offset += data.widthMultipliedByPixelSize) {
-            setPixel(data, paintingData, 0, y,
-                -1.0f / 2.0f, -data.upPixelValue() + data.upRightPixelValue() - 2 * data.centerPixelValue() + 2 * data.rightPixelValue() - data.downPixelValue() + data.downRightPixelValue(),
-                -1.0f / 3.0f, -2 * data.upPixelValue() - data.upRightPixelValue() + 2 * data.downPixelValue() + data.downRightPixelValue());
+        // Left column
+        offset = data.widthMultipliedByPixelSize;
+        for (int y = 1; y < data.heightDecreasedByOne; ++y, offset += data.widthMultipliedByPixelSize) {
+            data.leftColumn(offset, normalVector);
+            inlineSetPixel(offset, data, paintingData, 0, y, cFactor1div2, cFactor1div3, normalVector);
         }
-        // Right line
-        data.offset = data.widthMultipliedByPixelSize + data.widthMultipliedByPixelSize - cPixelSize;
-        for (int y = 1; y < data.heightDecreasedByOne; ++y, data.offset += data.widthMultipliedByPixelSize) {
-            setPixel(data, paintingData, data.widthDecreasedByOne, y,
-                -1.0f / 2.0f, -data.upLeftPixelValue() + data.upPixelValue() -2 * data.leftPixelValue() + 2 * data.centerPixelValue() - data.downLeftPixelValue() + data.downPixelValue(),
-                -1.0f / 3.0f, -data.upLeftPixelValue() - 2 * data.upPixelValue() + data.downLeftPixelValue() + 2 * data.downPixelValue());
+        // Right column
+        offset = (data.widthMultipliedByPixelSize << 1) - cPixelSize;
+        for (int y = 1; y < data.heightDecreasedByOne; ++y, offset += data.widthMultipliedByPixelSize) {
+            data.rightColumn(offset, normalVector);
+            inlineSetPixel(offset, data, paintingData, data.widthDecreasedByOne, y, cFactor1div2, cFactor1div3, normalVector);
         }
     }
 
     if (width >= 3 && height >= 3) {
         // Interior pixels
         for (int y = 1; y < data.heightDecreasedByOne; ++y) {
-            data.offset = y * data.widthMultipliedByPixelSize + cPixelSize;
-            for (int x = 1; x < data.widthDecreasedByOne; ++x, data.offset += cPixelSize) {
-                setPixel(data, paintingData, x, y,
-                    -1.0f / 4.0f, -data.upLeftPixelValue() + data.upRightPixelValue() - 2 * data.leftPixelValue() + 2 * data.rightPixelValue() - data.downLeftPixelValue() + data.downRightPixelValue(),
-                    -1.0f / 4.0f, -data.upLeftPixelValue() - 2 * data.upPixelValue() - data.upRightPixelValue() + data.downLeftPixelValue() + 2 * data.downPixelValue() + data.downRightPixelValue());
+            offset = y * data.widthMultipliedByPixelSize + cPixelSize;
+            for (int x = 1; x < data.widthDecreasedByOne; ++x, offset += cPixelSize) {
+                data.interior(offset, normalVector);
+                inlineSetPixel(offset, data, paintingData, x, y, cFactor1div4, cFactor1div4, normalVector);
             }
         }
     }
 
-    int totalSize = data.widthMultipliedByPixelSize * height;
+    int lastPixel = data.widthMultipliedByPixelSize * height;
     if (m_lightingType == DiffuseLighting) {
-        for (int i = 3; i < totalSize; i += 4)
+        for (int i = cAlphaChannelOffset; i < lastPixel; i += cPixelSize)
             data.pixels->set(i, cOpaqueAlpha);
     } else {
-        for (int i = 0; i < totalSize; i += 4) {
+        for (int i = 0; i < lastPixel; i += cPixelSize) {
             unsigned char a1 = data.pixels->get(i);
             unsigned char a2 = data.pixels->get(i + 1);
             unsigned char a3 = data.pixels->get(i + 2);
@@ -253,8 +342,8 @@ void FELighting::apply(Filter* filter)
     setIsAlphaImage(false);
 
     IntRect effectDrawingRect = requestedRegionOfInputImageData(in->absolutePaintRect());
-    RefPtr<ImageData> srcImageData(in->resultImage()->getUnmultipliedImageData(effectDrawingRect));
-    CanvasPixelArray* srcPixelArray(srcImageData->data());
+    RefPtr<ImageData> srcImageData = in->resultImage()->getUnmultipliedImageData(effectDrawingRect);
+    ByteArray* srcPixelArray = srcImageData->data()->data();
 
     // FIXME: support kernelUnitLengths other than (1,1). The issue here is that the W3
     // standard has no test case for them, and other browsers (like Firefox) has strange
diff --git a/WebCore/platform/graphics/filters/FELighting.h b/WebCore/platform/graphics/filters/FELighting.h
index bd56cee..c0f62ab 100644
--- a/WebCore/platform/graphics/filters/FELighting.h
+++ b/WebCore/platform/graphics/filters/FELighting.h
@@ -32,14 +32,12 @@
 #include "Filter.h"
 #include "FilterEffect.h"
 #include "LightSource.h"
-#include <wtf/AlwaysInline.h>
+#include <wtf/ByteArray.h>
 
 // Common base class for FEDiffuseLighting and FESpecularLighting
 
 namespace WebCore {
 
-class CanvasPixelArray;
-
 class FELighting : public FilterEffect {
 public:
     virtual void apply(Filter*);
@@ -53,31 +51,33 @@ protected:
     };
 
     struct LightingData {
-        FloatPoint3D normalVector;
-        CanvasPixelArray* pixels;
-        float lightStrength;
+        // This structure contains only read-only (SMP safe) data
+        ByteArray* pixels;
         float surfaceScale;
-        int offset;
         int widthMultipliedByPixelSize;
         int widthDecreasedByOne;
         int heightDecreasedByOne;
 
-        ALWAYS_INLINE int upLeftPixelValue();
-        ALWAYS_INLINE int upPixelValue();
-        ALWAYS_INLINE int upRightPixelValue();
-        ALWAYS_INLINE int leftPixelValue();
-        ALWAYS_INLINE int centerPixelValue();
-        ALWAYS_INLINE int rightPixelValue();
-        ALWAYS_INLINE int downLeftPixelValue();
-        ALWAYS_INLINE int downPixelValue();
-        ALWAYS_INLINE int downRightPixelValue();
+        inline void topLeft(int offset, IntPoint& normalVector);
+        inline void topRow(int offset, IntPoint& normalVector);
+        inline void topRight(int offset, IntPoint& normalVector);
+        inline void leftColumn(int offset, IntPoint& normalVector);
+        inline void interior(int offset, IntPoint& normalVector);
+        inline void rightColumn(int offset, IntPoint& normalVector);
+        inline void bottomLeft(int offset, IntPoint& normalVector);
+        inline void bottomRow(int offset, IntPoint& normalVector);
+        inline void bottomRight(int offset, IntPoint& normalVector);
     };
 
     FELighting(LightingType, const Color&, float, float, float, float, float, float, PassRefPtr<LightSource>);
 
-    bool drawLighting(CanvasPixelArray*, int, int);
-    ALWAYS_INLINE void setPixel(LightingData&, LightSource::PaintingData&,
-        int lightX, int lightY, float factorX, int normalX, float factorY, int normalY);
+    bool drawLighting(ByteArray*, int, int);
+    inline void inlineSetPixel(int offset, LightingData&, LightSource::PaintingData&,
+                               int lightX, int lightY, float factorX, float factorY, IntPoint& normalVector);
+
+    // Not worth to inline every occurence of setPixel.
+    void setPixel(int offset, LightingData&, LightSource::PaintingData&,
+                  int lightX, int lightY, float factorX, float factorY, IntPoint& normalVector);
 
     LightingType m_lightingType;
     RefPtr<LightSource> m_lightSource;
diff --git a/WebCore/platform/graphics/filters/LightSource.cpp b/WebCore/platform/graphics/filters/LightSource.cpp
index a80b14b..de0691e 100644
--- a/WebCore/platform/graphics/filters/LightSource.cpp
+++ b/WebCore/platform/graphics/filters/LightSource.cpp
@@ -42,7 +42,7 @@ void PointLightSource::updatePaintingData(PaintingData& paintingData, int x, int
     paintingData.lightVector.setX(m_position.x() - x);
     paintingData.lightVector.setY(m_position.y() - y);
     paintingData.lightVector.setZ(m_position.z() - z);
-    paintingData.lightVector.normalize();
+    paintingData.lightVectorLength = paintingData.lightVector.length();
 }
 
 // spot-light edge darkening depends on an absolute treshold
@@ -84,9 +84,9 @@ void SpotLightSource::updatePaintingData(PaintingData& paintingData, int x, int
     paintingData.lightVector.setX(m_position.x() - x);
     paintingData.lightVector.setY(m_position.y() - y);
     paintingData.lightVector.setZ(m_position.z() - z);
-    paintingData.lightVector.normalize();
+    paintingData.lightVectorLength = paintingData.lightVector.length();
 
-    float cosineOfAngle = paintingData.lightVector * paintingData.directionVector;
+    float cosineOfAngle = (paintingData.lightVector * paintingData.directionVector) / paintingData.lightVectorLength;
     if (cosineOfAngle > paintingData.coneCutOffLimit) {
         // No light is produced, scanlines are not updated
         paintingData.colorVector.setX(0.0f);
@@ -127,6 +127,7 @@ void DistantLightSource::initPaintingData(PaintingData& paintingData)
     paintingData.lightVector.setX(cosf(azimuth) * cosf(elevation));
     paintingData.lightVector.setY(sinf(azimuth) * cosf(elevation));
     paintingData.lightVector.setZ(sinf(elevation));
+    paintingData.lightVectorLength = 1;
 }
 
 void DistantLightSource::updatePaintingData(PaintingData&, int, int, float)
diff --git a/WebCore/platform/graphics/filters/LightSource.h b/WebCore/platform/graphics/filters/LightSource.h
index 2e4c579..013e910 100644
--- a/WebCore/platform/graphics/filters/LightSource.h
+++ b/WebCore/platform/graphics/filters/LightSource.h
@@ -51,6 +51,7 @@ public:
         // SVGFELighting also use them
         FloatPoint3D lightVector;
         FloatPoint3D colorVector;
+        float lightVectorLength;
         // Private members
         FloatPoint3D directionVector;
         FloatPoint3D privateColorVector;

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list