<!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>[167248] trunk</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/167248">167248</a></dd>
<dt>Author</dt> <dd>krit@webkit.org</dd>
<dt>Date</dt> <dd>2014-04-14 09:02:03 -0700 (Mon, 14 Apr 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>Optimize Canvas fill and drawImage with SourceIn, DestinationIn, SourceOut, and DestinationAtop using transparencyLayer.
https://bugs.webkit.org/show_bug.cgi?id=79659

Reviewed by Darin Adler.

Source/WebCore:
Optimize fill() and fillRect() operations in Canvas on composited contexts by
10 to 20 times on CG.

Replacing the ImageBuffer code by transparency layers allows the
graphics library to optimize the drawing.

Doing the same for drawImage() would give performance regressions.

An inline function will create a transparency layer for CG. Cairo graphics
does not composite correctly when a transparency layer gets created.
The inline function is just a NOOP for Cairo.

This fixes bug 131303 as well.

Added performance tests with <a href="http://trac.webkit.org/projects/webkit/changeset/167124">r167124</a> already.

* html/canvas/CanvasRenderingContext2D.cpp:
(WebCore::CanvasRenderingContext2D::fillInternal):
(WebCore::CanvasRenderingContext2D::strokeInternal):
(WebCore::CanvasRenderingContext2D::beginCompositeLayer):
(WebCore::CanvasRenderingContext2D::endCompositeLayer):
(WebCore::CanvasRenderingContext2D::fillRect):
(WebCore::CanvasRenderingContext2D::strokeRect):
(WebCore::CanvasRenderingContext2D::drawTextInternal):
(WebCore::CanvasRenderingContext2D::fullCanvasCompositedFill): Deleted.
* html/canvas/CanvasRenderingContext2D.h:

LayoutTests:
Unskip previously failing tests.

* platform/gtk/TestExpectations:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestsplatformgtkTestExpectations">trunk/LayoutTests/platform/gtk/TestExpectations</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCorehtmlcanvasCanvasRenderingContext2Dcpp">trunk/Source/WebCore/html/canvas/CanvasRenderingContext2D.cpp</a></li>
<li><a href="#trunkSourceWebCorehtmlcanvasCanvasRenderingContext2Dh">trunk/Source/WebCore/html/canvas/CanvasRenderingContext2D.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (167247 => 167248)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2014-04-14 15:48:44 UTC (rev 167247)
+++ trunk/LayoutTests/ChangeLog        2014-04-14 16:02:03 UTC (rev 167248)
</span><span class="lines">@@ -1,3 +1,14 @@
</span><ins>+2014-04-14  Dirk Schulze  &lt;krit@webkit.org&gt;
+
+        Optimize Canvas fill and drawImage with SourceIn, DestinationIn, SourceOut, and DestinationAtop using transparencyLayer.
+        https://bugs.webkit.org/show_bug.cgi?id=79659
+
+        Reviewed by Darin Adler.
+
+        Unskip previously failing tests.
+
+        * platform/gtk/TestExpectations:
+
</ins><span class="cx"> 2014-04-14  Manuel Rego Casasnovas  &lt;rego@igalia.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [JSC] CSSStyleDeclaration report incorrect descriptor
</span></span></pre></div>
<a id="trunkLayoutTestsplatformgtkTestExpectations"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/platform/gtk/TestExpectations (167247 => 167248)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/platform/gtk/TestExpectations        2014-04-14 15:48:44 UTC (rev 167247)
+++ trunk/LayoutTests/platform/gtk/TestExpectations        2014-04-14 16:02:03 UTC (rev 167248)
</span><span class="lines">@@ -1805,10 +1805,6 @@
</span><span class="cx"> webkit.org/b/107194 crypto/subtle/rsa-indexeddb.html [ Skip ]
</span><span class="cx"> webkit.org/b/107194 inspector-protocol/indexeddb/basics.html [ Skip ]
</span><span class="cx"> 
</span><del>-# Composite canvas tests with alpha failing.
-webkit.org/b/131303 fast/canvas/canvas-composite-stroke-alpha.html [ Failure ]
-webkit.org/b/131303 fast/canvas/canvas-composite-text-alpha.html [ Failure ]
-
</del><span class="cx"> # Test marked in TestExpectations as failing on non-retina displays, passing on GTK port
</span><span class="cx"> webkit.org/b/129113 fast/multicol/newmulticol/clipping.html [ Pass ]
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (167247 => 167248)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2014-04-14 15:48:44 UTC (rev 167247)
+++ trunk/Source/WebCore/ChangeLog        2014-04-14 16:02:03 UTC (rev 167248)
</span><span class="lines">@@ -1,3 +1,37 @@
</span><ins>+2014-04-14  Dirk Schulze  &lt;krit@webkit.org&gt;
+
+        Optimize Canvas fill and drawImage with SourceIn, DestinationIn, SourceOut, and DestinationAtop using transparencyLayer.
+        https://bugs.webkit.org/show_bug.cgi?id=79659
+
+        Reviewed by Darin Adler.
+
+        Optimize fill() and fillRect() operations in Canvas on composited contexts by
+        10 to 20 times on CG.
+
+        Replacing the ImageBuffer code by transparency layers allows the
+        graphics library to optimize the drawing.
+
+        Doing the same for drawImage() would give performance regressions.
+
+        An inline function will create a transparency layer for CG. Cairo graphics
+        does not composite correctly when a transparency layer gets created. 
+        The inline function is just a NOOP for Cairo.
+
+        This fixes bug 131303 as well.
+
+        Added performance tests with r167124 already.
+
+        * html/canvas/CanvasRenderingContext2D.cpp:
+        (WebCore::CanvasRenderingContext2D::fillInternal):
+        (WebCore::CanvasRenderingContext2D::strokeInternal):
+        (WebCore::CanvasRenderingContext2D::beginCompositeLayer):
+        (WebCore::CanvasRenderingContext2D::endCompositeLayer):
+        (WebCore::CanvasRenderingContext2D::fillRect):
+        (WebCore::CanvasRenderingContext2D::strokeRect):
+        (WebCore::CanvasRenderingContext2D::drawTextInternal):
+        (WebCore::CanvasRenderingContext2D::fullCanvasCompositedFill): Deleted.
+        * html/canvas/CanvasRenderingContext2D.h:
+
</ins><span class="cx"> 2014-04-14  Tim Horton  &lt;timothy_horton@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Lots of compositing test failures after r167152
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlcanvasCanvasRenderingContext2Dcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/canvas/CanvasRenderingContext2D.cpp (167247 => 167248)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/canvas/CanvasRenderingContext2D.cpp        2014-04-14 15:48:44 UTC (rev 167247)
+++ trunk/Source/WebCore/html/canvas/CanvasRenderingContext2D.cpp        2014-04-14 16:02:03 UTC (rev 167248)
</span><span class="lines">@@ -941,7 +941,9 @@
</span><span class="cx">         c-&gt;setFillRule(newWindRule);
</span><span class="cx"> 
</span><span class="cx">         if (isFullCanvasCompositeMode(state().m_globalComposite)) {
</span><del>-            fullCanvasCompositedFill(path);
</del><ins>+            beginCompositeLayer();
+            c-&gt;fillPath(path);
+            endCompositeLayer();
</ins><span class="cx">             didDrawEntireCanvas();
</span><span class="cx">         } else if (state().m_globalComposite == CompositeCopy) {
</span><span class="cx">             clearCanvas();
</span><span class="lines">@@ -971,9 +973,9 @@
</span><span class="cx"> 
</span><span class="cx">     if (!path.isEmpty()) {
</span><span class="cx">         if (isFullCanvasCompositeMode(state().m_globalComposite)) {
</span><del>-            c-&gt;beginTransparencyLayer(1);
</del><ins>+            beginCompositeLayer();
</ins><span class="cx">             c-&gt;strokePath(path);
</span><del>-            c-&gt;endTransparencyLayer();
</del><ins>+            endCompositeLayer();
</ins><span class="cx">             didDrawEntireCanvas();
</span><span class="cx">         } else if (state().m_globalComposite == CompositeCopy) {
</span><span class="cx">             clearCanvas();
</span><span class="lines">@@ -1004,6 +1006,20 @@
</span><span class="cx">     c-&gt;canvasClip(path, newWindRule);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+inline void CanvasRenderingContext2D::beginCompositeLayer()
+{
+#if !USE(CAIRO)
+    drawingContext()-&gt;beginTransparencyLayer(1);
+#endif
+}
+
+inline void CanvasRenderingContext2D::endCompositeLayer()
+{
+#if !USE(CAIRO)
+    drawingContext()-&gt;endTransparencyLayer();    
+#endif
+}
+
</ins><span class="cx"> bool CanvasRenderingContext2D::isPointInPath(const float x, const float y, const String&amp; windingRuleString)
</span><span class="cx"> {
</span><span class="cx">     return isPointInPathInternal(m_path, x, y, windingRuleString);
</span><span class="lines">@@ -1126,7 +1142,9 @@
</span><span class="cx">         c-&gt;fillRect(rect);
</span><span class="cx">         didDrawEntireCanvas();
</span><span class="cx">     } else if (isFullCanvasCompositeMode(state().m_globalComposite)) {
</span><del>-        fullCanvasCompositedFill(rect);
</del><ins>+        beginCompositeLayer();
+        c-&gt;fillRect(rect);
+        endCompositeLayer();
</ins><span class="cx">         didDrawEntireCanvas();
</span><span class="cx">     } else if (state().m_globalComposite == CompositeCopy) {
</span><span class="cx">         clearCanvas();
</span><span class="lines">@@ -1158,9 +1176,9 @@
</span><span class="cx"> 
</span><span class="cx">     FloatRect rect(x, y, width, height);
</span><span class="cx">     if (isFullCanvasCompositeMode(state().m_globalComposite)) {
</span><del>-        c-&gt;beginTransparencyLayer(1);
</del><ins>+        beginCompositeLayer();
</ins><span class="cx">         c-&gt;strokeRect(rect, state().m_lineWidth);
</span><del>-        c-&gt;endTransparencyLayer();
</del><ins>+        endCompositeLayer();
</ins><span class="cx">         didDrawEntireCanvas();
</span><span class="cx">     } else if (state().m_globalComposite == CompositeCopy) {
</span><span class="cx">         clearCanvas();
</span><span class="lines">@@ -1683,30 +1701,6 @@
</span><span class="cx">     compositeBuffer(buffer.get(), bufferRect, op);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-template&lt;class T&gt; void CanvasRenderingContext2D::fullCanvasCompositedFill(const T&amp; area)
-{
-    ASSERT(isFullCanvasCompositeMode(state().m_globalComposite));
-
-    IntRect bufferRect = calculateCompositingBufferRect(area, 0);
-    if (bufferRect.isEmpty()) {
-        clearCanvas();
-        return;
-    }
-
-    std::unique_ptr&lt;ImageBuffer&gt; buffer = createCompositingBuffer(bufferRect);
-    if (!buffer)
-        return;
-
-    Path path = transformAreaToDevice(area);
-    buffer-&gt;context()-&gt;setCompositeOperation(CompositeSourceOver);
-    buffer-&gt;context()-&gt;translate(FloatSize(-bufferRect.x(), -bufferRect.y()));
-    modifiableState().m_fillStyle.applyFillColor(buffer-&gt;context());
-
-    buffer-&gt;context()-&gt;fillPath(path);
-
-    compositeBuffer(buffer.get(), bufferRect, state().m_globalComposite);
-}
-
</del><span class="cx"> void CanvasRenderingContext2D::prepareGradientForDashboard(CanvasGradient* gradient) const
</span><span class="cx"> {
</span><span class="cx"> #if ENABLE(DASHBOARD_SUPPORT)
</span><span class="lines">@@ -2343,9 +2337,9 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     if (isFullCanvasCompositeMode(state().m_globalComposite)) {
</span><del>-        c-&gt;beginTransparencyLayer(1);
</del><ins>+        beginCompositeLayer();
</ins><span class="cx">         c-&gt;drawBidiText(font, textRun, location, Font::UseFallbackIfFontNotReady);
</span><del>-        c-&gt;endTransparencyLayer();
</del><ins>+        endCompositeLayer();
</ins><span class="cx">         didDrawEntireCanvas();
</span><span class="cx">     } else if (state().m_globalComposite == CompositeCopy) {
</span><span class="cx">         clearCanvas();
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlcanvasCanvasRenderingContext2Dh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/canvas/CanvasRenderingContext2D.h (167247 => 167248)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/canvas/CanvasRenderingContext2D.h        2014-04-14 15:48:44 UTC (rev 167247)
+++ trunk/Source/WebCore/html/canvas/CanvasRenderingContext2D.h        2014-04-14 16:02:03 UTC (rev 167248)
</span><span class="lines">@@ -304,6 +304,9 @@
</span><span class="cx">     void clearPathForDashboardBackwardCompatibilityMode();
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+    void beginCompositeLayer();
+    void endCompositeLayer();
+
</ins><span class="cx">     void fillInternal(const Path&amp;, const String&amp; winding);
</span><span class="cx">     void strokeInternal(const Path&amp;);
</span><span class="cx">     void clipInternal(const Path&amp;, const String&amp; winding);
</span><span class="lines">@@ -322,7 +325,6 @@
</span><span class="cx"> 
</span><span class="cx">     void inflateStrokeRect(FloatRect&amp;) const;
</span><span class="cx"> 
</span><del>-    template&lt;class T&gt; void fullCanvasCompositedFill(const T&amp;);
</del><span class="cx">     template&lt;class T&gt; void fullCanvasCompositedDrawImage(T*, ColorSpace, const FloatRect&amp;, const FloatRect&amp;, CompositeOperator);
</span><span class="cx"> 
</span><span class="cx">     void prepareGradientForDashboard(CanvasGradient* gradient) const;
</span></span></pre>
</div>
</div>

</body>
</html>