Title: [86931] trunk/Source/WebCore
Revision
86931
Author
[email protected]
Date
2011-05-20 01:53:05 -0700 (Fri, 20 May 2011)

Log Message

2011-05-20  Piroska András  <[email protected]>

        Reviewed by Nikolas Zimmermann.

        Apply the ParallelJobs support to FEConvolveMatrix
        https://bugs.webkit.org/show_bug.cgi?id=61171

        The FEConvolveMatrix filter of SVG can consume lots of resources if it is
        applied to a large area. The computation can be distributed to multiple
        cores if the architecture supports.
        The average performance progression is 20-30% on dual-core machines.

        Developed in cooperation with Gabor Loki.

        * platform/graphics/filters/FEConvolveMatrix.cpp:
        (WebCore::FEConvolveMatrix::fastSetInteriorPixels):
        (WebCore::FEConvolveMatrix::setInteriorPixels):
        (WebCore::FEConvolveMatrix::setInteriorPixelsWorker):
        (WebCore::FEConvolveMatrix::apply):
        * platform/graphics/filters/FEConvolveMatrix.h:

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (86930 => 86931)


--- trunk/Source/WebCore/ChangeLog	2011-05-20 08:48:12 UTC (rev 86930)
+++ trunk/Source/WebCore/ChangeLog	2011-05-20 08:53:05 UTC (rev 86931)
@@ -1,3 +1,24 @@
+2011-05-20  Piroska András  <[email protected]>
+
+        Reviewed by Nikolas Zimmermann.
+
+        Apply the ParallelJobs support to FEConvolveMatrix
+        https://bugs.webkit.org/show_bug.cgi?id=61171
+
+        The FEConvolveMatrix filter of SVG can consume lots of resources if it is
+        applied to a large area. The computation can be distributed to multiple
+        cores if the architecture supports.
+        The average performance progression is 20-30% on dual-core machines.
+
+        Developed in cooperation with Gabor Loki.
+
+        * platform/graphics/filters/FEConvolveMatrix.cpp:
+        (WebCore::FEConvolveMatrix::fastSetInteriorPixels):
+        (WebCore::FEConvolveMatrix::setInteriorPixels):
+        (WebCore::FEConvolveMatrix::setInteriorPixelsWorker):
+        (WebCore::FEConvolveMatrix::apply):
+        * platform/graphics/filters/FEConvolveMatrix.h:
+
 2011-05-20  Sheriff Bot  <[email protected]>
 
         Unreviewed, rolling out r86920.

Modified: trunk/Source/WebCore/platform/graphics/filters/FEConvolveMatrix.cpp (86930 => 86931)


--- trunk/Source/WebCore/platform/graphics/filters/FEConvolveMatrix.cpp	2011-05-20 08:48:12 UTC (rev 86930)
+++ trunk/Source/WebCore/platform/graphics/filters/FEConvolveMatrix.cpp	2011-05-20 08:53:05 UTC (rev 86931)
@@ -31,6 +31,7 @@
 #include "TextStream.h"
 
 #include <wtf/ByteArray.h>
+#include <wtf/ParallelJobs.h>
 
 namespace WebCore {
 
@@ -237,11 +238,10 @@
 
 // Only for region C
 template<bool preserveAlphaValues>
-ALWAYS_INLINE void FEConvolveMatrix::fastSetInteriorPixels(PaintingData& paintingData, int clipRight, int clipBottom)
+ALWAYS_INLINE void FEConvolveMatrix::fastSetInteriorPixels(PaintingData& paintingData, int clipRight, int clipBottom, int yStart, int yEnd)
 {
     // edge mode does not affect these pixels
     int pixel = (m_targetOffset.y() * paintingData.width + m_targetOffset.x()) * 4;
-    int startKernelPixel = 0;
     int kernelIncrease = clipRight * 4;
     int xIncrease = (m_kernelSize.width() - 1) * 4;
     // Contains the sum of rgb(a) components
@@ -250,7 +250,11 @@
     // m_divisor cannot be 0, SVGFEConvolveMatrixElement ensures this
     ASSERT(m_divisor);
 
-    for (int y = clipBottom + 1; y > 0; --y) {
+    // Skip the first '(clipBottom - yEnd)' lines
+    pixel += (clipBottom - yEnd) * (xIncrease + (clipRight + 1) * (preserveAlphaValues ? 3 : 4));
+    int startKernelPixel = (clipBottom - yEnd) * (xIncrease + (clipRight + 1) * 4);
+
+    for (int y = yEnd + 1; y > yStart; --y) {
         for (int x = clipRight + 1; x > 0; --x) {
             int kernelValue = m_kernelMatrix.size() - 1;
             int kernelPixel = startKernelPixel;
@@ -370,14 +374,14 @@
     }
 }
 
-ALWAYS_INLINE void FEConvolveMatrix::setInteriorPixels(PaintingData& paintingData, int clipRight, int clipBottom)
+ALWAYS_INLINE void FEConvolveMatrix::setInteriorPixels(PaintingData& paintingData, int clipRight, int clipBottom, int yStart, int yEnd)
 {
     // Must be implemented here, since it refers another ALWAYS_INLINE
     // function, which defined in this C++ source file as well
     if (m_preserveAlpha)
-        fastSetInteriorPixels<true>(paintingData, clipRight, clipBottom);
+        fastSetInteriorPixels<true>(paintingData, clipRight, clipBottom, yStart, yEnd);
     else
-        fastSetInteriorPixels<false>(paintingData, clipRight, clipBottom);
+        fastSetInteriorPixels<false>(paintingData, clipRight, clipBottom, yStart, yEnd);
 }
 
 ALWAYS_INLINE void FEConvolveMatrix::setOuterPixels(PaintingData& paintingData, int x1, int y1, int x2, int y2)
@@ -390,6 +394,13 @@
         fastSetOuterPixels<false>(paintingData, x1, y1, x2, y2);
 }
 
+#if ENABLE(PARALLEL_JOBS)
+void FEConvolveMatrix::setInteriorPixelsWorker(InteriorPixelParameters* param)
+{
+    param->filter->setInteriorPixels(*param->paintingData, param->clipRight, param->clipBottom, param->yStart, param->yEnd);
+}
+#endif
+
 void FEConvolveMatrix::apply()
 {
     if (hasResult())
@@ -428,8 +439,35 @@
     int clipBottom = paintSize.height() - m_kernelSize.height();
 
     if (clipRight >= 0 && clipBottom >= 0) {
-        setInteriorPixels(paintingData, clipRight, clipBottom);
 
+#if ENABLE(PARALLEL_JOBS)
+        int optimalThreadNumber = (absolutePaintRect().width() * absolutePaintRect().height()) / s_minimalRectDimension;
+        if (optimalThreadNumber > 1) {
+            ParallelJobs<InteriorPixelParameters> parallelJobs(&WebCore::FEConvolveMatrix::setInteriorPixelsWorker, optimalThreadNumber);
+            const int numOfThreads = parallelJobs.numberOfJobs();
+            const int heightPerThread = clipBottom / numOfThreads;
+            int startY = 0;
+
+            for (int job = 0; job < numOfThreads; ++job) {
+                InteriorPixelParameters& param = parallelJobs.parameter(job);
+                param.filter = this;
+                param.paintingData = &paintingData;
+                param.clipRight = clipRight;
+                param.clipBottom = clipBottom;
+                param.yStart = startY;
+                if (i < numOfThreads - 1) {
+                    startY += heightPerThread;
+                    param.yEnd = startY - 1;
+                } else
+                    param.yEnd = clipBottom;
+            }
+
+            parallelJobs.execute();
+        } else
+            // Fallback to the default setInteriorPixels call.
+#endif
+        setInteriorPixels(paintingData, clipRight, clipBottom, 0, clipBottom);
+
         clipRight += m_targetOffset.x() + 1;
         clipBottom += m_targetOffset.y() + 1;
         if (m_targetOffset.y() > 0)

Modified: trunk/Source/WebCore/platform/graphics/filters/FEConvolveMatrix.h (86930 => 86931)


--- trunk/Source/WebCore/platform/graphics/filters/FEConvolveMatrix.h	2011-05-20 08:48:12 UTC (rev 86930)
+++ trunk/Source/WebCore/platform/graphics/filters/FEConvolveMatrix.h	2011-05-20 08:53:05 UTC (rev 86931)
@@ -80,8 +80,6 @@
     virtual TextStream& externalRepresentation(TextStream&, int indention) const;
 
 private:
-    FEConvolveMatrix(Filter*, const IntSize&, float, float,
-            const IntPoint&, EdgeModeType, const FloatPoint&, bool, const Vector<float>&);
 
     struct PaintingData {
         ByteArray* srcPixelArray;
@@ -91,8 +89,11 @@
         float bias;
     };
 
+    FEConvolveMatrix(Filter*, const IntSize&, float, float,
+            const IntPoint&, EdgeModeType, const FloatPoint&, bool, const Vector<float>&);
+
     template<bool preserveAlphaValues>
-    ALWAYS_INLINE void fastSetInteriorPixels(PaintingData&, int clipRight, int clipBottom);
+    ALWAYS_INLINE void fastSetInteriorPixels(PaintingData&, int clipRight, int clipBottom, int yStart, int yEnd);
 
     ALWAYS_INLINE int getPixelValue(PaintingData&, int x, int y);
 
@@ -100,9 +101,28 @@
     void fastSetOuterPixels(PaintingData&, int x1, int y1, int x2, int y2);
 
     // Wrapper functions
-    ALWAYS_INLINE void setInteriorPixels(PaintingData& paintingData, int clipRight, int clipBottom);
-    ALWAYS_INLINE void setOuterPixels(PaintingData& paintingData, int x1, int y1, int x2, int y2);
+    ALWAYS_INLINE void setInteriorPixels(PaintingData&, int clipRight, int clipBottom, int yStart, int yEnd);
+    ALWAYS_INLINE void setOuterPixels(PaintingData&, int x1, int y1, int x2, int y2);
 
+    // Parallelization parts
+#if ENABLE(PARALLEL_JOBS)
+    static const int s_minimalRectDimension = (100 * 100); // Empirical data limit for parallel jobs
+
+    template<typename Type>
+    friend class ParallelJobs;
+
+    struct InteriorPixelParameters {
+        FEConvolveMatrix* filter;
+        PaintingData* paintingData;
+        int clipBottom;
+        int clipRight;
+        int yStart;
+        int yEnd;
+    };
+
+    static void setInteriorPixelsWorker(InteriorPixelParameters*);
+#endif
+
     IntSize m_kernelSize;
     float m_divisor;
     float m_bias;
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to