<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[214916] trunk/Source/WebCore</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/214916">214916</a></dd>
<dt>Author</dt> <dd>simon.fraser@apple.com</dd>
<dt>Date</dt> <dd>2017-04-04 17:23:46 -0700 (Tue, 04 Apr 2017)</dd>
</dl>

<h3>Log Message</h3>
<pre>Do some minor FEColorMatrix code cleanup and optimization
https://bugs.webkit.org/show_bug.cgi?id=170474

Reviewed by Dean Jackson.

Don't switch inside of a pixel processing loop; repeat the loop inside switch (filterType).

Change matrix() and saturateAndHueRotate() to dereference the source pixels once, instead
of multiple times, which is faster.

This kind of code benefits from aligning things with spaces for readability, so do so,
violating webkit style.

Add some off-by-default performance logging code.

Increases pixel processing performance from about 86ms per megapixel to 65ms per megapixel.

* platform/graphics/filters/FEColorMatrix.cpp:
(WebCore::matrix):
(WebCore::saturateAndHueRotate):
(WebCore::effectType):
(WebCore::FEColorMatrix::platformApplySoftware):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsfiltersFEColorMatrixcpp">trunk/Source/WebCore/platform/graphics/filters/FEColorMatrix.cpp</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (214915 => 214916)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2017-04-05 00:05:27 UTC (rev 214915)
+++ trunk/Source/WebCore/ChangeLog        2017-04-05 00:23:46 UTC (rev 214916)
</span><span class="lines">@@ -1,3 +1,28 @@
</span><ins>+2017-04-04  Simon Fraser  &lt;simon.fraser@apple.com&gt;
+
+        Do some minor FEColorMatrix code cleanup and optimization
+        https://bugs.webkit.org/show_bug.cgi?id=170474
+
+        Reviewed by Dean Jackson.
+
+        Don't switch inside of a pixel processing loop; repeat the loop inside switch (filterType).
+        
+        Change matrix() and saturateAndHueRotate() to dereference the source pixels once, instead
+        of multiple times, which is faster.
+        
+        This kind of code benefits from aligning things with spaces for readability, so do so,
+        violating webkit style.
+        
+        Add some off-by-default performance logging code.
+
+        Increases pixel processing performance from about 86ms per megapixel to 65ms per megapixel.
+
+        * platform/graphics/filters/FEColorMatrix.cpp:
+        (WebCore::matrix):
+        (WebCore::saturateAndHueRotate):
+        (WebCore::effectType):
+        (WebCore::FEColorMatrix::platformApplySoftware):
+
</ins><span class="cx"> 2017-04-04  Brent Fulgham  &lt;bfulgham@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Do not assert when CharacterData representing an Attr fires events
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsfiltersFEColorMatrixcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/filters/FEColorMatrix.cpp (214915 => 214916)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/filters/FEColorMatrix.cpp        2017-04-05 00:05:27 UTC (rev 214915)
+++ trunk/Source/WebCore/platform/graphics/filters/FEColorMatrix.cpp        2017-04-05 00:23:46 UTC (rev 214916)
</span><span class="lines">@@ -30,6 +30,8 @@
</span><span class="cx"> #include &lt;runtime/Uint8ClampedArray.h&gt;
</span><span class="cx"> #include &lt;wtf/MathExtras.h&gt;
</span><span class="cx"> 
</span><ins>+#define PRINT_FILTER_PERFORMANCE 0
+
</ins><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><span class="cx"> FEColorMatrix::FEColorMatrix(Filter&amp; filter, ColorMatrixType type, const Vector&lt;float&gt;&amp; values)
</span><span class="lines">@@ -72,26 +74,26 @@
</span><span class="cx"> 
</span><span class="cx"> inline void matrix(float&amp; red, float&amp; green, float&amp; blue, float&amp; alpha, const Vector&lt;float&gt;&amp; values)
</span><span class="cx"> {
</span><del>-    float r = values[0] * red + values[1] * green + values[2] * blue + values[3] * alpha + values[4] * 255;
-    float g = values[5] * red + values[6] * green + values[7] * blue + values[8] * alpha + values[9] * 255;
-    float b = values[10] * red + values[11] * green + values[12] * blue + values[13] * alpha + values[14] * 255;
-    float a = values[15] * red + values[16] * green + values[17] * blue + values[18] * alpha + values[19] * 255;
</del><ins>+    float r = red;
+    float g = green;
+    float b = blue;
+    float a = alpha;
</ins><span class="cx"> 
</span><del>-    red = r;
-    green = g;
-    blue = b;
-    alpha = a;
</del><ins>+    red     = values[ 0] * r + values[ 1] * g + values[ 2] * b + values[ 3] * a + values[ 4] * 255;
+    green   = values[ 5] * r + values[ 6] * g + values [7] * b + values[ 8] * a + values[ 9] * 255;
+    blue    = values[10] * r + values[11] * g + values[12] * b + values[13] * a + values[14] * 255;
+    alpha   = values[15] * r + values[16] * g + values[17] * b + values[18] * a + values[19] * 255;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> inline void saturateAndHueRotate(float&amp; red, float&amp; green, float&amp; blue, const float* components)
</span><span class="cx"> {
</span><del>-    float r = red * components[0] + green * components[1] + blue * components[2];
-    float g = red * components[3] + green * components[4] + blue * components[5];
-    float b = red * components[6] + green * components[7] + blue * components[8];
</del><ins>+    float r = red;
+    float g = green;
+    float b = blue;
</ins><span class="cx"> 
</span><del>-    red = r;
-    green = g;
-    blue = b;
</del><ins>+    red     = r * components[0] + g * components[1] + b * components[2];
+    green   = r * components[3] + g * components[4] + b * components[5];
+    blue    = r * components[6] + g * components[7] + b * components[8];
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> inline void luminance(float&amp; red, float&amp; green, float&amp; blue, float&amp; alpha)
</span><span class="lines">@@ -105,7 +107,6 @@
</span><span class="cx"> template&lt;ColorMatrixType filterType&gt;
</span><span class="cx"> void effectType(Uint8ClampedArray* pixelArray, const Vector&lt;float&gt;&amp; values)
</span><span class="cx"> {
</span><del>-    unsigned pixelArrayLength = pixelArray-&gt;length();
</del><span class="cx">     float components[9];
</span><span class="cx"> 
</span><span class="cx">     if (filterType == FECOLORMATRIX_TYPE_SATURATE)
</span><span class="lines">@@ -113,29 +114,51 @@
</span><span class="cx">     else if (filterType == FECOLORMATRIX_TYPE_HUEROTATE)
</span><span class="cx">         FEColorMatrix::calculateHueRotateComponents(components, values[0]);
</span><span class="cx"> 
</span><del>-    for (unsigned pixelByteOffset = 0; pixelByteOffset &lt; pixelArrayLength; pixelByteOffset += 4) {
-        float red = pixelArray-&gt;item(pixelByteOffset);
-        float green = pixelArray-&gt;item(pixelByteOffset + 1);
-        float blue = pixelArray-&gt;item(pixelByteOffset + 2);
-        float alpha = pixelArray-&gt;item(pixelByteOffset + 3);
</del><ins>+    unsigned pixelArrayLength = pixelArray-&gt;length();
</ins><span class="cx"> 
</span><del>-        switch (filterType) {
-            case FECOLORMATRIX_TYPE_MATRIX:
-                matrix(red, green, blue, alpha, values);
-                break;
-            case FECOLORMATRIX_TYPE_SATURATE:
-            case FECOLORMATRIX_TYPE_HUEROTATE:
-                saturateAndHueRotate(red, green, blue, components);
-                break;
-            case FECOLORMATRIX_TYPE_LUMINANCETOALPHA:
-                luminance(red, green, blue, alpha);
-                break;
</del><ins>+    switch (filterType) {
+    case FECOLORMATRIX_TYPE_MATRIX:
+        for (unsigned pixelByteOffset = 0; pixelByteOffset &lt; pixelArrayLength; pixelByteOffset += 4) {
+            float red = pixelArray-&gt;item(pixelByteOffset);
+            float green = pixelArray-&gt;item(pixelByteOffset + 1);
+            float blue = pixelArray-&gt;item(pixelByteOffset + 2);
+            float alpha = pixelArray-&gt;item(pixelByteOffset + 3);
+            matrix(red, green, blue, alpha, values);
+            pixelArray-&gt;set(pixelByteOffset, red);
+            pixelArray-&gt;set(pixelByteOffset + 1, green);
+            pixelArray-&gt;set(pixelByteOffset + 2, blue);
+            pixelArray-&gt;set(pixelByteOffset + 3, alpha);
</ins><span class="cx">         }
</span><ins>+        break;
</ins><span class="cx"> 
</span><del>-        pixelArray-&gt;set(pixelByteOffset, red);
-        pixelArray-&gt;set(pixelByteOffset + 1, green);
-        pixelArray-&gt;set(pixelByteOffset + 2, blue);
-        pixelArray-&gt;set(pixelByteOffset + 3, alpha);
</del><ins>+    case FECOLORMATRIX_TYPE_SATURATE:
+    case FECOLORMATRIX_TYPE_HUEROTATE:
+        for (unsigned pixelByteOffset = 0; pixelByteOffset &lt; pixelArrayLength; pixelByteOffset += 4) {
+            float red = pixelArray-&gt;item(pixelByteOffset);
+            float green = pixelArray-&gt;item(pixelByteOffset + 1);
+            float blue = pixelArray-&gt;item(pixelByteOffset + 2);
+            float alpha = pixelArray-&gt;item(pixelByteOffset + 3);
+            saturateAndHueRotate(red, green, blue, components);
+            pixelArray-&gt;set(pixelByteOffset, red);
+            pixelArray-&gt;set(pixelByteOffset + 1, green);
+            pixelArray-&gt;set(pixelByteOffset + 2, blue);
+            pixelArray-&gt;set(pixelByteOffset + 3, alpha);
+        }
+        break;
+
+    case FECOLORMATRIX_TYPE_LUMINANCETOALPHA:
+        for (unsigned pixelByteOffset = 0; pixelByteOffset &lt; pixelArrayLength; pixelByteOffset += 4) {
+            float red = pixelArray-&gt;item(pixelByteOffset);
+            float green = pixelArray-&gt;item(pixelByteOffset + 1);
+            float blue = pixelArray-&gt;item(pixelByteOffset + 2);
+            float alpha = pixelArray-&gt;item(pixelByteOffset + 3);
+            luminance(red, green, blue, alpha);
+            pixelArray-&gt;set(pixelByteOffset, red);
+            pixelArray-&gt;set(pixelByteOffset + 1, green);
+            pixelArray-&gt;set(pixelByteOffset + 2, blue);
+            pixelArray-&gt;set(pixelByteOffset + 3, alpha);
+        }
+        break;
</ins><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -147,6 +170,10 @@
</span><span class="cx">     if (!resultImage)
</span><span class="cx">         return;
</span><span class="cx"> 
</span><ins>+#if PRINT_FILTER_PERFORMANCE
+    MonotonicTime startTime = MonotonicTime::now();
+#endif
+
</ins><span class="cx">     ImageBuffer* inBuffer = in-&gt;asImageBuffer();
</span><span class="cx">     if (inBuffer)
</span><span class="cx">         resultImage-&gt;context().drawImageBuffer(*inBuffer, drawingRegionOfInputImage(in-&gt;absolutePaintRect()));
</span><span class="lines">@@ -174,6 +201,20 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     resultImage-&gt;putByteArray(Unmultiplied, pixelArray.get(), imageRect.size(), imageRect, IntPoint());
</span><ins>+
+#if PRINT_FILTER_PERFORMANCE
+    MonotonicTime endTime = MonotonicTime::now();
+    Seconds duration = endTime - startTime;
+    unsigned pixelCount = imageRect.width() * imageRect.height();
+    
+    static double totalMegapixels;
+    totalMegapixels += (double)pixelCount / 1048576.0;
+    
+    static Seconds totalTime;
+    totalTime += duration;
+    
+    WTFLogAlways(&quot;FEColorMatrix::platformApplySoftware (%dx%d) took %.4fms (ave %.4fms/mp)&quot;, imageRect.width(), imageRect.height(), duration.milliseconds(), totalTime.milliseconds() / totalMegapixels);
+#endif
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void FEColorMatrix::dump()
</span></span></pre>
</div>
</div>

</body>
</html>