<!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>[195646] 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/195646">195646</a></dd>
<dt>Author</dt> <dd>simon.fraser@apple.com</dd>
<dt>Date</dt> <dd>2016-01-26 17:53:18 -0800 (Tue, 26 Jan 2016)</dd>
</dl>
<h3>Log Message</h3>
<pre>Allow canvas to use display-list drawing for testing
https://bugs.webkit.org/show_bug.cgi?id=153475
Reviewed by Dean Jackson.
Source/WebCore:
Optionally have 2D <canvas> use display-list drawing, which is only enabled
via Internals for now.
Support displayListAsText() and replayDisplayListAsText() on canvas, so we can
use it to test playback optimizations. [Note that displayListAsText() always
returns an empty string currently, because the display list is cleared when the
canvas is painted to the page.]
Display list rendering is implemented by giving CanvasRenderingContext2D an
optional DisplayListDrawingContext, which packages up a display list, recorder
and recording context. The existing paintRenderingResultsToCanvas() is overridden
to replay the recorded display list into the primary canvas context.
Tracked replay display lists are stored in a static map, keyed by the CanvasRenderingContext2D.
Test: displaylists/canvas-display-list.html
* html/HTMLCanvasElement.cpp:
(WebCore::HTMLCanvasElement::HTMLCanvasElement):
(WebCore::HTMLCanvasElement::getContext):
(WebCore::HTMLCanvasElement::paint):
(WebCore::HTMLCanvasElement::setUsesDisplayListDrawing):
(WebCore::HTMLCanvasElement::setTracksDisplayListReplay):
(WebCore::HTMLCanvasElement::displayListAsText):
(WebCore::HTMLCanvasElement::replayDisplayListAsText):
* html/HTMLCanvasElement.h:
* html/canvas/CanvasRenderingContext.h:
* html/canvas/CanvasRenderingContext2D.cpp:
(WebCore::DisplayListDrawingContext::DisplayListDrawingContext):
(WebCore::contextDisplayListMap):
(WebCore::CanvasRenderingContext2D::~CanvasRenderingContext2D):
(WebCore::CanvasRenderingContext2D::setTracksDisplayListReplay):
(WebCore::CanvasRenderingContext2D::displayListAsText):
(WebCore::CanvasRenderingContext2D::replayDisplayListAsText):
(WebCore::CanvasRenderingContext2D::paintRenderingResultsToCanvas):
(WebCore::CanvasRenderingContext2D::drawingContext):
(WebCore::CanvasRenderingContext2D::CanvasRenderingContext2D): Deleted.
* html/canvas/CanvasRenderingContext2D.h:
* testing/Internals.cpp:
(WebCore::Internals::setElementUsesDisplayListDrawing):
(WebCore::Internals::setElementTracksDisplayListReplay):
(WebCore::Internals::displayListForElement):
(WebCore::Internals::replayDisplayListForElement):
LayoutTests:
Simple canvas-based display list test.
* displaylists/canvas-display-list-expected.txt: Added.
* displaylists/canvas-display-list.html: Added.</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCorehtmlHTMLCanvasElementcpp">trunk/Source/WebCore/html/HTMLCanvasElement.cpp</a></li>
<li><a href="#trunkSourceWebCorehtmlHTMLCanvasElementh">trunk/Source/WebCore/html/HTMLCanvasElement.h</a></li>
<li><a href="#trunkSourceWebCorehtmlcanvasCanvasRenderingContexth">trunk/Source/WebCore/html/canvas/CanvasRenderingContext.h</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>
<li><a href="#trunkSourceWebCoretestingInternalscpp">trunk/Source/WebCore/testing/Internals.cpp</a></li>
</ul>
<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsdisplaylistscanvasdisplaylistexpectedtxt">trunk/LayoutTests/displaylists/canvas-display-list-expected.txt</a></li>
<li><a href="#trunkLayoutTestsdisplaylistscanvasdisplaylisthtml">trunk/LayoutTests/displaylists/canvas-display-list.html</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (195645 => 195646)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2016-01-27 01:31:36 UTC (rev 195645)
+++ trunk/LayoutTests/ChangeLog        2016-01-27 01:53:18 UTC (rev 195646)
</span><span class="lines">@@ -1,3 +1,15 @@
</span><ins>+2016-01-26 Simon Fraser <simon.fraser@apple.com>
+
+ Allow canvas to use display-list drawing for testing
+ https://bugs.webkit.org/show_bug.cgi?id=153475
+
+ Reviewed by Dean Jackson.
+
+ Simple canvas-based display list test.
+
+ * displaylists/canvas-display-list-expected.txt: Added.
+ * displaylists/canvas-display-list.html: Added.
+
</ins><span class="cx"> 2016-01-26 Chris Dumez <cdumez@apple.com>
</span><span class="cx">
</span><span class="cx"> Setting HTMLInputElement.value to null to set its value to the empty string
</span></span></pre></div>
<a id="trunkLayoutTestsdisplaylistscanvasdisplaylistexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/displaylists/canvas-display-list-expected.txt (0 => 195646)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/displaylists/canvas-display-list-expected.txt         (rev 0)
+++ trunk/LayoutTests/displaylists/canvas-display-list-expected.txt        2016-01-27 01:53:18 UTC (rev 195646)
</span><span class="lines">@@ -0,0 +1,13 @@
</span><ins>+
+(set-state
+ (change-flags 256)
+ (fill-color #C80000))
+(fill-rect
+ (extent at (10,10) size 55x50)
+ (rect at (10,10) size 55x50))
+(set-state
+ (change-flags 256)
+ (fill-color #0000C87F))
+(fill-rect
+ (extent at (30,30) size 55x50)
+ (rect at (30,30) size 55x50))
</ins></span></pre></div>
<a id="trunkLayoutTestsdisplaylistscanvasdisplaylisthtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/displaylists/canvas-display-list.html (0 => 195646)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/displaylists/canvas-display-list.html         (rev 0)
+++ trunk/LayoutTests/displaylists/canvas-display-list.html        2016-01-27 01:53:18 UTC (rev 195646)
</span><span class="lines">@@ -0,0 +1,44 @@
</span><ins>+<!DOCTYPE html>
+
+<html>
+<head>
+ <script>
+ function drawCanvas()
+ {
+ var ctx = document.getElementById('canvas').getContext('2d');
+ ctx.fillStyle = "rgb(200,0,0)";
+ ctx.fillRect (10, 10, 55, 50);
+
+ ctx.fillStyle = "rgba(0, 0, 200, 0.5)";
+ ctx.fillRect (30, 30, 55, 50);
+ }
+
+ if (window.testRunner)
+ testRunner.dumpAsText();
+
+ var canvas;
+ function doTest()
+ {
+ document.body.offsetWidth;
+ canvas = document.getElementById('canvas');
+ if (window.internals) {
+ internals.setElementUsesDisplayListDrawing(canvas, true);
+ internals.setElementTracksDisplayListReplay(canvas, true);
+ }
+
+ drawCanvas();
+
+ if (window.testRunner)
+ testRunner.display();
+
+ if (window.internals)
+ document.getElementById('output').textContent = internals.replayDisplayListForElement(canvas);
+ }
+ window.addEventListener('load', doTest, false);
+ </script>
+</head>
+<body>
+<canvas id="canvas" width="300" height="200"></canvas>
+<pre id="output"></pre>
+</body>
+</html>
</ins></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (195645 => 195646)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2016-01-27 01:31:36 UTC (rev 195645)
+++ trunk/Source/WebCore/ChangeLog        2016-01-27 01:53:18 UTC (rev 195646)
</span><span class="lines">@@ -1,3 +1,54 @@
</span><ins>+2016-01-26 Simon Fraser <simon.fraser@apple.com>
+
+ Allow canvas to use display-list drawing for testing
+ https://bugs.webkit.org/show_bug.cgi?id=153475
+
+ Reviewed by Dean Jackson.
+
+ Optionally have 2D <canvas> use display-list drawing, which is only enabled
+ via Internals for now.
+
+ Support displayListAsText() and replayDisplayListAsText() on canvas, so we can
+ use it to test playback optimizations. [Note that displayListAsText() always
+ returns an empty string currently, because the display list is cleared when the
+ canvas is painted to the page.]
+
+ Display list rendering is implemented by giving CanvasRenderingContext2D an
+ optional DisplayListDrawingContext, which packages up a display list, recorder
+ and recording context. The existing paintRenderingResultsToCanvas() is overridden
+ to replay the recorded display list into the primary canvas context.
+
+ Tracked replay display lists are stored in a static map, keyed by the CanvasRenderingContext2D.
+
+ Test: displaylists/canvas-display-list.html
+
+ * html/HTMLCanvasElement.cpp:
+ (WebCore::HTMLCanvasElement::HTMLCanvasElement):
+ (WebCore::HTMLCanvasElement::getContext):
+ (WebCore::HTMLCanvasElement::paint):
+ (WebCore::HTMLCanvasElement::setUsesDisplayListDrawing):
+ (WebCore::HTMLCanvasElement::setTracksDisplayListReplay):
+ (WebCore::HTMLCanvasElement::displayListAsText):
+ (WebCore::HTMLCanvasElement::replayDisplayListAsText):
+ * html/HTMLCanvasElement.h:
+ * html/canvas/CanvasRenderingContext.h:
+ * html/canvas/CanvasRenderingContext2D.cpp:
+ (WebCore::DisplayListDrawingContext::DisplayListDrawingContext):
+ (WebCore::contextDisplayListMap):
+ (WebCore::CanvasRenderingContext2D::~CanvasRenderingContext2D):
+ (WebCore::CanvasRenderingContext2D::setTracksDisplayListReplay):
+ (WebCore::CanvasRenderingContext2D::displayListAsText):
+ (WebCore::CanvasRenderingContext2D::replayDisplayListAsText):
+ (WebCore::CanvasRenderingContext2D::paintRenderingResultsToCanvas):
+ (WebCore::CanvasRenderingContext2D::drawingContext):
+ (WebCore::CanvasRenderingContext2D::CanvasRenderingContext2D): Deleted.
+ * html/canvas/CanvasRenderingContext2D.h:
+ * testing/Internals.cpp:
+ (WebCore::Internals::setElementUsesDisplayListDrawing):
+ (WebCore::Internals::setElementTracksDisplayListReplay):
+ (WebCore::Internals::displayListForElement):
+ (WebCore::Internals::replayDisplayListForElement):
+
</ins><span class="cx"> 2016-01-26 Joseph Pecoraro <pecoraro@apple.com>
</span><span class="cx">
</span><span class="cx"> Generalize ResourceUsageData gathering to be used outside of ResourceUsageOverlay
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlHTMLCanvasElementcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/HTMLCanvasElement.cpp (195645 => 195646)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/HTMLCanvasElement.cpp        2016-01-27 01:31:36 UTC (rev 195645)
+++ trunk/Source/WebCore/html/HTMLCanvasElement.cpp        2016-01-27 01:53:18 UTC (rev 195646)
</span><span class="lines">@@ -232,6 +232,10 @@
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> m_context = std::make_unique<CanvasRenderingContext2D>(this, document().inQuirksMode(), usesDashbardCompatibilityMode);
</span><ins>+
+ downcast<CanvasRenderingContext2D>(*m_context).setUsesDisplayListDrawing(m_usesDisplayListDrawing);
+ downcast<CanvasRenderingContext2D>(*m_context).setTracksDisplayListReplay(m_tracksDisplayListReplay);
+
</ins><span class="cx"> #if USE(IOSURFACE_CANVAS_BACKING_STORE) || ENABLE(ACCELERATED_2D_CANVAS)
</span><span class="cx"> // Need to make sure a RenderLayer and compositing layer get created for the Canvas
</span><span class="cx"> setNeedsStyleRecalc(SyntheticStyleChange);
</span><span class="lines">@@ -410,6 +414,7 @@
</span><span class="cx"> if (m_context) {
</span><span class="cx"> if (!paintsIntoCanvasBuffer() && !document().printing())
</span><span class="cx"> return;
</span><ins>+
</ins><span class="cx"> m_context->paintRenderingResultsToCanvas();
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -589,6 +594,44 @@
</span><span class="cx"> return 4 * m_imageBuffer->internalSize().width() * m_imageBuffer->internalSize().height();
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+void HTMLCanvasElement::setUsesDisplayListDrawing(bool usesDisplayListDrawing)
+{
+ if (usesDisplayListDrawing == m_usesDisplayListDrawing)
+ return;
+
+ m_usesDisplayListDrawing = usesDisplayListDrawing;
+
+ if (m_context && is<CanvasRenderingContext2D>(*m_context))
+ downcast<CanvasRenderingContext2D>(*m_context).setUsesDisplayListDrawing(m_usesDisplayListDrawing);
+}
+
+void HTMLCanvasElement::setTracksDisplayListReplay(bool tracksDisplayListReplay)
+{
+ if (tracksDisplayListReplay == m_tracksDisplayListReplay)
+ return;
+
+ m_tracksDisplayListReplay = tracksDisplayListReplay;
+
+ if (m_context && is<CanvasRenderingContext2D>(*m_context))
+ downcast<CanvasRenderingContext2D>(*m_context).setTracksDisplayListReplay(m_tracksDisplayListReplay);
+}
+
+String HTMLCanvasElement::displayListAsText(DisplayList::AsTextFlags flags) const
+{
+ if (m_context && is<CanvasRenderingContext2D>(*m_context))
+ return downcast<CanvasRenderingContext2D>(*m_context).displayListAsText(flags);
+
+ return String();
+}
+
+String HTMLCanvasElement::replayDisplayListAsText(DisplayList::AsTextFlags flags) const
+{
+ if (m_context && is<CanvasRenderingContext2D>(*m_context))
+ return downcast<CanvasRenderingContext2D>(*m_context).replayDisplayListAsText(flags);
+
+ return String();
+}
+
</ins><span class="cx"> void HTMLCanvasElement::createImageBuffer() const
</span><span class="cx"> {
</span><span class="cx"> ASSERT(!m_imageBuffer);
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlHTMLCanvasElementh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/HTMLCanvasElement.h (195645 => 195646)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/HTMLCanvasElement.h        2016-01-27 01:31:36 UTC (rev 195645)
+++ trunk/Source/WebCore/html/HTMLCanvasElement.h        2016-01-27 01:53:18 UTC (rev 195646)
</span><span class="lines">@@ -52,6 +52,10 @@
</span><span class="cx"> class ImageBuffer;
</span><span class="cx"> class IntSize;
</span><span class="cx">
</span><ins>+namespace DisplayList {
+typedef unsigned AsTextFlags;
+}
+
</ins><span class="cx"> class CanvasObserver {
</span><span class="cx"> public:
</span><span class="cx"> virtual ~CanvasObserver() { }
</span><span class="lines">@@ -135,6 +139,11 @@
</span><span class="cx">
</span><span class="cx"> bool shouldAccelerate(const IntSize&) const;
</span><span class="cx">
</span><ins>+ WEBCORE_EXPORT void setUsesDisplayListDrawing(bool);
+ WEBCORE_EXPORT void setTracksDisplayListReplay(bool);
+ WEBCORE_EXPORT String displayListAsText(DisplayList::AsTextFlags) const;
+ WEBCORE_EXPORT String replayDisplayListAsText(DisplayList::AsTextFlags) const;
+
</ins><span class="cx"> size_t memoryCost() const;
</span><span class="cx">
</span><span class="cx"> private:
</span><span class="lines">@@ -171,6 +180,9 @@
</span><span class="cx"> bool m_rendererIsCanvas { false };
</span><span class="cx"> bool m_ignoreReset { false };
</span><span class="cx">
</span><ins>+ bool m_usesDisplayListDrawing { false };
+ bool m_tracksDisplayListReplay { false };
+
</ins><span class="cx"> // m_createdImageBuffer means we tried to malloc the buffer. We didn't necessarily get it.
</span><span class="cx"> mutable bool m_hasCreatedImageBuffer { false };
</span><span class="cx"> mutable bool m_didClearImageBuffer { false };
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlcanvasCanvasRenderingContexth"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/canvas/CanvasRenderingContext.h (195645 => 195646)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/canvas/CanvasRenderingContext.h        2016-01-27 01:31:36 UTC (rev 195645)
+++ trunk/Source/WebCore/html/canvas/CanvasRenderingContext.h        2016-01-27 01:53:18 UTC (rev 195646)
</span><span class="lines">@@ -81,4 +81,9 @@
</span><span class="cx">
</span><span class="cx"> } // namespace WebCore
</span><span class="cx">
</span><ins>+#define SPECIALIZE_TYPE_TRAITS_CANVASRENDERINGCONTEXT(ToValueTypeName, predicate) \
+SPECIALIZE_TYPE_TRAITS_BEGIN(ToValueTypeName) \
+ static bool isType(const WebCore::CanvasRenderingContext& context) { return context.predicate; } \
+SPECIALIZE_TYPE_TRAITS_END()
+
</ins><span class="cx"> #endif
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlcanvasCanvasRenderingContext2Dcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/canvas/CanvasRenderingContext2D.cpp (195645 => 195646)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/canvas/CanvasRenderingContext2D.cpp        2016-01-27 01:31:36 UTC (rev 195645)
+++ trunk/Source/WebCore/html/canvas/CanvasRenderingContext2D.cpp        2016-01-27 01:53:18 UTC (rev 195646)
</span><span class="lines">@@ -40,6 +40,8 @@
</span><span class="cx"> #include "CanvasGradient.h"
</span><span class="cx"> #include "CanvasPattern.h"
</span><span class="cx"> #include "DOMPath.h"
</span><ins>+#include "DisplayListRecorder.h"
+#include "DisplayListReplayer.h"
</ins><span class="cx"> #include "ExceptionCodePlaceholder.h"
</span><span class="cx"> #include "FloatQuad.h"
</span><span class="cx"> #include "HTMLImageElement.h"
</span><span class="lines">@@ -55,6 +57,7 @@
</span><span class="cx"> #include "StyleResolver.h"
</span><span class="cx"> #include "TextMetrics.h"
</span><span class="cx"> #include "TextRun.h"
</span><ins>+#include "TextStream.h"
</ins><span class="cx">
</span><span class="cx"> #include <wtf/CheckedArithmetic.h>
</span><span class="cx"> #include <wtf/MathExtras.h>
</span><span class="lines">@@ -85,6 +88,25 @@
</span><span class="cx"> static const char* const defaultFontFamily = "sans-serif";
</span><span class="cx"> static const char* const defaultFont = "10px sans-serif";
</span><span class="cx">
</span><ins>+struct DisplayListDrawingContext {
+ GraphicsContext context;
+ DisplayList::Recorder recorder;
+ DisplayList::DisplayList displayList;
+
+ DisplayListDrawingContext(const FloatRect& clip)
+ : recorder(context, displayList, clip, AffineTransform())
+ {
+ }
+};
+
+typedef HashMap<const CanvasRenderingContext2D*, std::unique_ptr<DisplayList::DisplayList>> ContextDisplayListHashMap;
+
+static ContextDisplayListHashMap& contextDisplayListMap()
+{
+ static NeverDestroyed<ContextDisplayListHashMap> sharedHashMap;
+ return sharedHashMap;
+}
+
</ins><span class="cx"> class CanvasStrokeStyleApplier : public StrokeStyleApplier {
</span><span class="cx"> public:
</span><span class="cx"> CanvasStrokeStyleApplier(CanvasRenderingContext2D* canvasContext)
</span><span class="lines">@@ -112,7 +134,6 @@
</span><span class="cx"> CanvasRenderingContext2D::CanvasRenderingContext2D(HTMLCanvasElement* canvas, bool usesCSSCompatibilityParseMode, bool usesDashboardCompatibilityMode)
</span><span class="cx"> : CanvasRenderingContext(canvas)
</span><span class="cx"> , m_stateStack(1)
</span><del>- , m_unrealizedSaveCount(0)
</del><span class="cx"> , m_usesCSSCompatibilityParseMode(usesCSSCompatibilityParseMode)
</span><span class="cx"> #if ENABLE(DASHBOARD_SUPPORT)
</span><span class="cx"> , m_usesDashboardCompatibilityMode(usesDashboardCompatibilityMode)
</span><span class="lines">@@ -141,6 +162,9 @@
</span><span class="cx"> #if !ASSERT_DISABLED
</span><span class="cx"> unwindStateStack();
</span><span class="cx"> #endif
</span><ins>+
+ if (UNLIKELY(tracksDisplayListReplay()))
+ contextDisplayListMap().remove(this);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> bool CanvasRenderingContext2D::isAccelerated() const
</span><span class="lines">@@ -162,6 +186,8 @@
</span><span class="cx"> m_stateStack.first() = State();
</span><span class="cx"> m_path.clear();
</span><span class="cx"> m_unrealizedSaveCount = 0;
</span><ins>+
+ m_recordingContext = nullptr;
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> CanvasRenderingContext2D::State::State()
</span><span class="lines">@@ -1907,8 +1933,64 @@
</span><span class="cx"> canvas()->didDraw(dirtyRect);
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+void CanvasRenderingContext2D::setTracksDisplayListReplay(bool tracksDisplayListReplay)
+{
+ if (tracksDisplayListReplay == m_tracksDisplayListReplay)
+ return;
+
+ m_tracksDisplayListReplay = tracksDisplayListReplay;
+ if (!m_tracksDisplayListReplay)
+ contextDisplayListMap().remove(this);
+}
+
+String CanvasRenderingContext2D::displayListAsText(DisplayList::AsTextFlags flags) const
+{
+ if (m_recordingContext)
+ return m_recordingContext->displayList.asText(flags);
+
+ return String();
+}
+
+String CanvasRenderingContext2D::replayDisplayListAsText(DisplayList::AsTextFlags flags) const
+{
+ auto it = contextDisplayListMap().find(this);
+ if (it != contextDisplayListMap().end()) {
+ TextStream stream;
+ stream << it->value->asText(flags);
+ return stream.release();
+ }
+
+ return String();
+}
+
+void CanvasRenderingContext2D::paintRenderingResultsToCanvas()
+{
+ if (UNLIKELY(m_usesDisplayListDrawing)) {
+ if (!m_recordingContext)
+ return;
+
+ FloatRect clip(FloatPoint::zero(), canvas()->size());
+ DisplayList::Replayer replayer(*canvas()->drawingContext(), m_recordingContext->displayList);
+
+ if (UNLIKELY(m_tracksDisplayListReplay)) {
+ auto replayList = replayer.replay(clip, m_tracksDisplayListReplay);
+ contextDisplayListMap().add(this, WTFMove(replayList));
+ } else
+ replayer.replay(clip);
+
+ m_recordingContext->displayList.clear();
+ }
+}
+
</ins><span class="cx"> GraphicsContext* CanvasRenderingContext2D::drawingContext() const
</span><span class="cx"> {
</span><ins>+ if (UNLIKELY(m_usesDisplayListDrawing)) {
+ if (!m_recordingContext)
+ m_recordingContext = std::make_unique<DisplayListDrawingContext>(FloatRect(FloatPoint::zero(), canvas()->size()));
+
+ return &m_recordingContext->context;
+ }
+
</ins><span class="cx"> return canvas()->drawingContext();
</span><span class="cx"> }
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlcanvasCanvasRenderingContext2Dh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/canvas/CanvasRenderingContext2D.h (195645 => 195646)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/canvas/CanvasRenderingContext2D.h        2016-01-27 01:31:36 UTC (rev 195645)
+++ trunk/Source/WebCore/html/canvas/CanvasRenderingContext2D.h        2016-01-27 01:53:18 UTC (rev 195646)
</span><span class="lines">@@ -237,6 +237,15 @@
</span><span class="cx"> High
</span><span class="cx"> };
</span><span class="cx">
</span><ins>+ bool usesDisplayListDrawing() const { return m_usesDisplayListDrawing; };
+ void setUsesDisplayListDrawing(bool flag) { m_usesDisplayListDrawing = flag; };
+
+ bool tracksDisplayListReplay() const { return m_tracksDisplayListReplay; }
+ void setTracksDisplayListReplay(bool);
+
+ String displayListAsText(DisplayList::AsTextFlags) const;
+ String replayDisplayListAsText(DisplayList::AsTextFlags) const;
+
</ins><span class="cx"> private:
</span><span class="cx"> enum class Direction {
</span><span class="cx"> Inherit,
</span><span class="lines">@@ -320,6 +329,8 @@
</span><span class="cx"> void didDraw(const FloatRect&, unsigned options = CanvasDidDrawApplyAll);
</span><span class="cx"> void didDrawEntireCanvas();
</span><span class="cx">
</span><ins>+ void paintRenderingResultsToCanvas() override;
+
</ins><span class="cx"> GraphicsContext* drawingContext() const;
</span><span class="cx">
</span><span class="cx"> void unwindStateStack();
</span><span class="lines">@@ -384,13 +395,19 @@
</span><span class="cx"> #endif
</span><span class="cx">
</span><span class="cx"> Vector<State, 1> m_stateStack;
</span><del>- unsigned m_unrealizedSaveCount;
</del><ins>+ unsigned m_unrealizedSaveCount { 0 };
</ins><span class="cx"> bool m_usesCSSCompatibilityParseMode;
</span><span class="cx"> #if ENABLE(DASHBOARD_SUPPORT)
</span><span class="cx"> bool m_usesDashboardCompatibilityMode;
</span><span class="cx"> #endif
</span><ins>+
+ bool m_usesDisplayListDrawing { false };
+ bool m_tracksDisplayListReplay { false };
+ mutable std::unique_ptr<struct DisplayListDrawingContext> m_recordingContext;
</ins><span class="cx"> };
</span><span class="cx">
</span><span class="cx"> } // namespace WebCore
</span><span class="cx">
</span><ins>+SPECIALIZE_TYPE_TRAITS_CANVASRENDERINGCONTEXT(WebCore::CanvasRenderingContext2D, is2d())
+
</ins><span class="cx"> #endif
</span></span></pre></div>
<a id="trunkSourceWebCoretestingInternalscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/testing/Internals.cpp (195645 => 195646)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/testing/Internals.cpp        2016-01-27 01:31:36 UTC (rev 195645)
+++ trunk/Source/WebCore/testing/Internals.cpp        2016-01-27 01:53:18 UTC (rev 195646)
</span><span class="lines">@@ -57,6 +57,7 @@
</span><span class="cx"> #include "FormController.h"
</span><span class="cx"> #include "FrameLoader.h"
</span><span class="cx"> #include "FrameView.h"
</span><ins>+#include "HTMLCanvasElement.h"
</ins><span class="cx"> #include "HTMLIFrameElement.h"
</span><span class="cx"> #include "HTMLImageElement.h"
</span><span class="cx"> #include "HTMLInputElement.h"
</span><span class="lines">@@ -1982,11 +1983,21 @@
</span><span class="cx"> return;
</span><span class="cx"> }
</span><span class="cx">
</span><del>- if (!element || !element->renderer() || !element->renderer()->hasLayer()) {
</del><ins>+ if (!element || !element->renderer()) {
</ins><span class="cx"> ec = INVALID_ACCESS_ERR;
</span><span class="cx"> return;
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+ if (is<HTMLCanvasElement>(*element)) {
+ downcast<HTMLCanvasElement>(*element).setUsesDisplayListDrawing(usesDisplayListDrawing);
+ return;
+ }
+
+ if (!element->renderer()->hasLayer()) {
+ ec = INVALID_ACCESS_ERR;
+ return;
+ }
+
</ins><span class="cx"> RenderLayer* layer = downcast<RenderLayerModelObject>(element->renderer())->layer();
</span><span class="cx"> if (!layer->isComposited()) {
</span><span class="cx"> ec = INVALID_ACCESS_ERR;
</span><span class="lines">@@ -2004,11 +2015,21 @@
</span><span class="cx"> return;
</span><span class="cx"> }
</span><span class="cx">
</span><del>- if (!element || !element->renderer() || !element->renderer()->hasLayer()) {
</del><ins>+ if (!element || !element->renderer()) {
</ins><span class="cx"> ec = INVALID_ACCESS_ERR;
</span><span class="cx"> return;
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+ if (is<HTMLCanvasElement>(*element)) {
+ downcast<HTMLCanvasElement>(*element).setTracksDisplayListReplay(isTrackingReplay);
+ return;
+ }
+
+ if (!element->renderer()->hasLayer()) {
+ ec = INVALID_ACCESS_ERR;
+ return;
+ }
+
</ins><span class="cx"> RenderLayer* layer = downcast<RenderLayerModelObject>(element->renderer())->layer();
</span><span class="cx"> if (!layer->isComposited()) {
</span><span class="cx"> ec = INVALID_ACCESS_ERR;
</span><span class="lines">@@ -2031,21 +2052,29 @@
</span><span class="cx"> return String();
</span><span class="cx"> }
</span><span class="cx">
</span><del>- if (!element || !element->renderer() || !element->renderer()->hasLayer()) {
</del><ins>+ if (!element || !element->renderer()) {
</ins><span class="cx"> ec = INVALID_ACCESS_ERR;
</span><span class="cx"> return String();
</span><span class="cx"> }
</span><del>-
</del><ins>+
+ DisplayList::AsTextFlags displayListFlags = 0;
+ if (flags & DISPLAY_LIST_INCLUDES_PLATFORM_OPERATIONS)
+ displayListFlags |= DisplayList::AsTextFlag::IncludesPlatformOperations;
+
+ if (is<HTMLCanvasElement>(*element))
+ return downcast<HTMLCanvasElement>(*element).displayListAsText(displayListFlags);
+
+ if (!element->renderer()->hasLayer()) {
+ ec = INVALID_ACCESS_ERR;
+ return String();
+ }
+
</ins><span class="cx"> RenderLayer* layer = downcast<RenderLayerModelObject>(element->renderer())->layer();
</span><span class="cx"> if (!layer->isComposited()) {
</span><span class="cx"> ec = INVALID_ACCESS_ERR;
</span><span class="cx"> return String();
</span><span class="cx"> }
</span><span class="cx">
</span><del>- DisplayList::AsTextFlags displayListFlags = 0;
- if (flags & DISPLAY_LIST_INCLUDES_PLATFORM_OPERATIONS)
- displayListFlags |= DisplayList::AsTextFlag::IncludesPlatformOperations;
-
</del><span class="cx"> return layer->backing()->displayListAsText(displayListFlags);
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -2062,21 +2091,29 @@
</span><span class="cx"> return String();
</span><span class="cx"> }
</span><span class="cx">
</span><del>- if (!element || !element->renderer() || !element->renderer()->hasLayer()) {
</del><ins>+ if (!element || !element->renderer()) {
</ins><span class="cx"> ec = INVALID_ACCESS_ERR;
</span><span class="cx"> return String();
</span><span class="cx"> }
</span><del>-
</del><ins>+
+ DisplayList::AsTextFlags displayListFlags = 0;
+ if (flags & DISPLAY_LIST_INCLUDES_PLATFORM_OPERATIONS)
+ displayListFlags |= DisplayList::AsTextFlag::IncludesPlatformOperations;
+
+ if (is<HTMLCanvasElement>(*element))
+ return downcast<HTMLCanvasElement>(*element).replayDisplayListAsText(displayListFlags);
+
+ if (!element->renderer()->hasLayer()) {
+ ec = INVALID_ACCESS_ERR;
+ return String();
+ }
+
</ins><span class="cx"> RenderLayer* layer = downcast<RenderLayerModelObject>(element->renderer())->layer();
</span><span class="cx"> if (!layer->isComposited()) {
</span><span class="cx"> ec = INVALID_ACCESS_ERR;
</span><span class="cx"> return String();
</span><span class="cx"> }
</span><span class="cx">
</span><del>- DisplayList::AsTextFlags displayListFlags = 0;
- if (flags & DISPLAY_LIST_INCLUDES_PLATFORM_OPERATIONS)
- displayListFlags |= DisplayList::AsTextFlag::IncludesPlatformOperations;
-
</del><span class="cx"> return layer->backing()->replayDisplayListAsText(displayListFlags);
</span><span class="cx"> }
</span><span class="cx">
</span></span></pre>
</div>
</div>
</body>
</html>