Add testing for display list replay, and skip clipped-out items on replay
authorsimon.fraser@apple.com <simon.fraser@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 24 Jan 2016 20:39:42 +0000 (20:39 +0000)
committersimon.fraser@apple.com <simon.fraser@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 24 Jan 2016 20:39:42 +0000 (20:39 +0000)
https://bugs.webkit.org/show_bug.cgi?id=153408

Reviewed by Zalan Bujtas.
Source/WebCore:

Make it possible to save and serialize a DisplayList of Items which were
actually applied on replay, so that replay-time optimizations can be tested.

This exposes internals.setElementTracksDisplayListReplay() and
internals.replayDisplayListForElement().

Do a trivial replay-time optimization, which is to skip items whose extents are
outside the replay clip.

Test: displaylists/replay-skip-clipped-rect.html

* platform/graphics/GraphicsLayer.cpp:
(WebCore::GraphicsLayer::GraphicsLayer):
* platform/graphics/GraphicsLayer.h:
(WebCore::GraphicsLayer::setIsTrackingDisplayListReplay):
(WebCore::GraphicsLayer::isTrackingDisplayListReplay):
(WebCore::GraphicsLayer::replayDisplayListAsText):
* platform/graphics/ca/GraphicsLayerCA.cpp:
(WebCore::layerDisplayListMap): Use a singleton map to store the replay display lists
to avoid bloating GraphicsLayerCA for test-only code. The map stores a pair of the
replay list and a clip rect, which are both dumped. Dumping the clip rect ensures that
we're reporting the replay for the correct tile in a test (since there will be a replay
for each tile).
(WebCore::GraphicsLayerCA::~GraphicsLayerCA):
(WebCore::GraphicsLayerCA::platformCALayerPaintContents):
(WebCore::GraphicsLayerCA::setIsTrackingDisplayListReplay):
(WebCore::GraphicsLayerCA::replayDisplayListAsText):
* platform/graphics/ca/GraphicsLayerCA.h:
* platform/graphics/displaylists/DisplayList.h:
(WebCore::DisplayList::DisplayList::appendItem):
* platform/graphics/displaylists/DisplayListReplayer.cpp:
(WebCore::DisplayList::Replayer::replay): In the unlikely event of tracking replays,
allocate a new DisplayList and append to it items which actually get applied.
* platform/graphics/displaylists/DisplayListReplayer.h:
* rendering/RenderLayerBacking.cpp:
(WebCore::RenderLayerBacking::setIsTrackingDisplayListReplay):
(WebCore::RenderLayerBacking::replayDisplayListAsText):
* rendering/RenderLayerBacking.h:
* testing/Internals.cpp:
(WebCore::Internals::setElementTracksDisplayListReplay):
(WebCore::Internals::replayDisplayListForElement):
* testing/Internals.h:
* testing/Internals.idl:

LayoutTests:

Test that a clipped-out rectangle is not painted.

In order to get the rect into the display list, we need to make the target
compositing layer be tiled, and to be clipped by an ancestor so that only the
second tile renders. (This complexity is required because in simpler scenarios,
the rect is clipped out at recording time.)

* displaylists/replay-skip-clipped-rect-expected.txt: Added.
* displaylists/replay-skip-clipped-rect.html: Added.
* displaylists/resources/dump-target-replay-list.js: Added.
(doTest):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@195515 268f45cc-cd09-0410-ab3c-d52691b4dbfc

17 files changed:
LayoutTests/ChangeLog
LayoutTests/displaylists/replay-skip-clipped-rect-expected.txt [new file with mode: 0644]
LayoutTests/displaylists/replay-skip-clipped-rect.html [new file with mode: 0644]
LayoutTests/displaylists/resources/dump-target-replay-list.js [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/platform/graphics/GraphicsLayer.cpp
Source/WebCore/platform/graphics/GraphicsLayer.h
Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp
Source/WebCore/platform/graphics/ca/GraphicsLayerCA.h
Source/WebCore/platform/graphics/displaylists/DisplayList.h
Source/WebCore/platform/graphics/displaylists/DisplayListReplayer.cpp
Source/WebCore/platform/graphics/displaylists/DisplayListReplayer.h
Source/WebCore/rendering/RenderLayerBacking.cpp
Source/WebCore/rendering/RenderLayerBacking.h
Source/WebCore/testing/Internals.cpp
Source/WebCore/testing/Internals.h
Source/WebCore/testing/Internals.idl

index f002ef5..d1cf9af 100644 (file)
@@ -1,3 +1,22 @@
+2016-01-24  Simon Fraser  <simon.fraser@apple.com>
+
+        Add testing for display list replay, and skip clipped-out items on replay
+        https://bugs.webkit.org/show_bug.cgi?id=153408
+
+        Reviewed by Zalan Bujtas.
+
+        Test that a clipped-out rectangle is not painted.
+
+        In order to get the rect into the display list, we need to make the target
+        compositing layer be tiled, and to be clipped by an ancestor so that only the
+        second tile renders. (This complexity is required because in simpler scenarios,
+        the rect is clipped out at recording time.)
+
+        * displaylists/replay-skip-clipped-rect-expected.txt: Added.
+        * displaylists/replay-skip-clipped-rect.html: Added.
+        * displaylists/resources/dump-target-replay-list.js: Added.
+        (doTest):
+
 2016-01-23  Simon Fraser  <simon.fraser@apple.com>
 
         Layout Test displaylists/extent-includes-transforms.html is flaky on mac-wk1
diff --git a/LayoutTests/displaylists/replay-skip-clipped-rect-expected.txt b/LayoutTests/displaylists/replay-skip-clipped-rect-expected.txt
new file mode 100644 (file)
index 0000000..888cc47
--- /dev/null
@@ -0,0 +1,16 @@
+recorded: 
+(
+  (translate
+    (x 0.00)
+    (y 0.00)))
+(
+  (fill-rect-with-color
+    (extent at (412,0) size 100x100)
+    (rect at (412,0) size 100x100)
+    (color #0000FF)))
+
+replayed: 
+(
+  (translate
+    (x 0.00)
+    (y 0.00)))
diff --git a/LayoutTests/displaylists/replay-skip-clipped-rect.html b/LayoutTests/displaylists/replay-skip-clipped-rect.html
new file mode 100644 (file)
index 0000000..0ff47f8
--- /dev/null
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+
+<html>
+<head>
+    <style>
+        #clipper {
+            height: 200px;
+            width: 200px;
+            overflow: hidden;
+            -webkit-transform: translateZ(0);
+        }
+        #target {
+            /* Tiled layer, shifted to show the second tile. */
+            height: 200px;
+            width: 3200px;
+            -webkit-transform: translate3d(-512px, 0, 0);
+        }
+        
+        .shadowed {
+            /* Just outside the second tile. */
+            margin-left: 412px;
+            width: 100px;
+            height: 100px;
+            background-color: blue;
+        }
+        
+    </style>
+    <script src="resources/dump-target-replay-list.js"></script>
+</head>
+<body>
+    
+<div id="clipper">
+    <div id="target">
+        <div class="shadowed">
+        </div>
+    </div>
+</div>
+
+<pre id="output"></pre>
+</body>
+</html>
diff --git a/LayoutTests/displaylists/resources/dump-target-replay-list.js b/LayoutTests/displaylists/resources/dump-target-replay-list.js
new file mode 100644 (file)
index 0000000..c84fede
--- /dev/null
@@ -0,0 +1,23 @@
+if (window.testRunner)
+    testRunner.dumpAsText();
+
+var targetDiv;
+function doTest()
+{
+    document.body.offsetWidth;
+    targetDiv = document.getElementById('target');
+    if (window.internals) {
+        internals.setElementUsesDisplayListDrawing(targetDiv, true);
+        internals.setElementTracksDisplayListReplay(targetDiv, true);
+    }
+    
+    if (window.testRunner)
+        testRunner.display();
+
+    if (window.internals) {
+        var displayList = internals.displayListForElement(targetDiv);
+        var replayList = internals.replayDisplayListForElement(targetDiv);
+        document.getElementById('output').textContent = 'recorded: ' + displayList + '\n\nreplayed: ' + replayList;
+    }
+}
+window.addEventListener('load', doTest, false);
index b98dd14..7fa71fb 100644 (file)
@@ -1,3 +1,54 @@
+2016-01-24  Simon Fraser  <simon.fraser@apple.com>
+
+        Add testing for display list replay, and skip clipped-out items on replay
+        https://bugs.webkit.org/show_bug.cgi?id=153408
+
+        Reviewed by Zalan Bujtas.
+        
+        Make it possible to save and serialize a DisplayList of Items which were
+        actually applied on replay, so that replay-time optimizations can be tested.
+        
+        This exposes internals.setElementTracksDisplayListReplay() and
+        internals.replayDisplayListForElement().
+        
+        Do a trivial replay-time optimization, which is to skip items whose extents are
+        outside the replay clip.
+
+        Test: displaylists/replay-skip-clipped-rect.html
+
+        * platform/graphics/GraphicsLayer.cpp:
+        (WebCore::GraphicsLayer::GraphicsLayer):
+        * platform/graphics/GraphicsLayer.h:
+        (WebCore::GraphicsLayer::setIsTrackingDisplayListReplay):
+        (WebCore::GraphicsLayer::isTrackingDisplayListReplay):
+        (WebCore::GraphicsLayer::replayDisplayListAsText):
+        * platform/graphics/ca/GraphicsLayerCA.cpp:
+        (WebCore::layerDisplayListMap): Use a singleton map to store the replay display lists
+        to avoid bloating GraphicsLayerCA for test-only code. The map stores a pair of the
+        replay list and a clip rect, which are both dumped. Dumping the clip rect ensures that
+        we're reporting the replay for the correct tile in a test (since there will be a replay
+        for each tile).
+        (WebCore::GraphicsLayerCA::~GraphicsLayerCA):
+        (WebCore::GraphicsLayerCA::platformCALayerPaintContents):
+        (WebCore::GraphicsLayerCA::setIsTrackingDisplayListReplay):
+        (WebCore::GraphicsLayerCA::replayDisplayListAsText):
+        * platform/graphics/ca/GraphicsLayerCA.h:
+        * platform/graphics/displaylists/DisplayList.h:
+        (WebCore::DisplayList::DisplayList::appendItem):
+        * platform/graphics/displaylists/DisplayListReplayer.cpp:
+        (WebCore::DisplayList::Replayer::replay): In the unlikely event of tracking replays,
+        allocate a new DisplayList and append to it items which actually get applied.
+        * platform/graphics/displaylists/DisplayListReplayer.h:
+        * rendering/RenderLayerBacking.cpp:
+        (WebCore::RenderLayerBacking::setIsTrackingDisplayListReplay):
+        (WebCore::RenderLayerBacking::replayDisplayListAsText):
+        * rendering/RenderLayerBacking.h:
+        * testing/Internals.cpp:
+        (WebCore::Internals::setElementTracksDisplayListReplay):
+        (WebCore::Internals::replayDisplayListForElement):
+        * testing/Internals.h:
+        * testing/Internals.idl:
+
 2016-01-23  Wonchul Lee  <wonchul.lee@collabora.co.uk>
 
         [GTK] Fix media controls displaying without controls attribute
index 0e8dd75..3411fe0 100644 (file)
@@ -127,6 +127,7 @@ GraphicsLayer::GraphicsLayer(Type type, GraphicsLayerClient& client)
     , m_showDebugBorder(false)
     , m_showRepaintCounter(false)
     , m_isMaskLayer(false)
+    , m_isTrackingDisplayListReplay(false)
     , m_paintingPhase(GraphicsLayerPaintAllWithOverflowClip)
     , m_contentsOrientation(CompositingCoordinatesTopDown)
     , m_parent(nullptr)
index f26f883..1a4a17e 100644 (file)
@@ -524,6 +524,10 @@ public:
     // For testing.
     WEBCORE_EXPORT virtual String displayListAsText(DisplayList::AsTextFlags) const { return String(); }
 
+    WEBCORE_EXPORT virtual void setIsTrackingDisplayListReplay(bool isTracking) { m_isTrackingDisplayListReplay = isTracking; }
+    WEBCORE_EXPORT virtual bool isTrackingDisplayListReplay() const { return m_isTrackingDisplayListReplay; }
+    WEBCORE_EXPORT virtual String replayDisplayListAsText(DisplayList::AsTextFlags) const { return String(); }
+
     // Return an estimate of the backing store memory cost (in bytes). May be incorrect for tiled layers.
     WEBCORE_EXPORT virtual double backingStoreMemoryEstimate() const;
 
@@ -621,6 +625,7 @@ protected:
     bool m_showDebugBorder : 1;
     bool m_showRepaintCounter : 1;
     bool m_isMaskLayer : 1;
+    bool m_isTrackingDisplayListReplay : 1;
     
     GraphicsLayerPaintingPhase m_paintingPhase;
     CompositingCoordinatesOrientation m_contentsOrientation; // affects orientation of layer contents
index 90b7c53..8058641 100644 (file)
@@ -47,6 +47,7 @@
 #include <limits.h>
 #include <wtf/CurrentTime.h>
 #include <wtf/MathExtras.h>
+#include <wtf/NeverDestroyed.h>
 #include <wtf/SystemTracing.h>
 #include <wtf/TemporaryChange.h>
 #include <wtf/text/WTFString.h>
@@ -357,6 +358,14 @@ PassRefPtr<PlatformCAAnimation> GraphicsLayerCA::createPlatformCAAnimation(Platf
 #endif
 }
 
+typedef HashMap<const GraphicsLayerCA*, std::pair<FloatRect, std::unique_ptr<DisplayList::DisplayList>>> LayerDisplayListHashMap;
+
+static LayerDisplayListHashMap& layerDisplayListMap()
+{
+    static NeverDestroyed<LayerDisplayListHashMap> sharedHashMap;
+    return sharedHashMap;
+}
+
 GraphicsLayerCA::GraphicsLayerCA(Type layerType, GraphicsLayerClient& client)
     : GraphicsLayer(layerType, client)
     , m_needsFullRepaint(false)
@@ -390,6 +399,9 @@ void GraphicsLayerCA::initialize(Type layerType)
 
 GraphicsLayerCA::~GraphicsLayerCA()
 {
+    if (UNLIKELY(isTrackingDisplayListReplay()))
+        layerDisplayListMap().remove(this);
+
     // Do cleanup while we can still safely call methods on the derived class.
     willBeDestroyed();
 }
@@ -1445,7 +1457,13 @@ void GraphicsLayerCA::platformCALayerPaintContents(PlatformCALayer*, GraphicsCon
     m_hasEverPainted = true;
     if (m_displayList) {
         DisplayList::Replayer replayer(context, *m_displayList);
-        replayer.replay(clip);
+        
+        if (UNLIKELY(isTrackingDisplayListReplay())) {
+            auto replayList = replayer.replay(clip, isTrackingDisplayListReplay());
+            layerDisplayListMap().add(this, std::pair<FloatRect, std::unique_ptr<DisplayList::DisplayList>>(clip, WTFMove(replayList)));
+        } else
+            replayer.replay(clip);
+
         return;
     }
 
@@ -3279,6 +3297,32 @@ String GraphicsLayerCA::displayListAsText(DisplayList::AsTextFlags flags) const
     return m_displayList->asText(flags);
 }
 
+void GraphicsLayerCA::setIsTrackingDisplayListReplay(bool isTracking)
+{
+    if (isTracking == m_isTrackingDisplayListReplay)
+        return;
+
+    m_isTrackingDisplayListReplay = isTracking;
+    if (!m_isTrackingDisplayListReplay)
+        layerDisplayListMap().remove(this);
+}
+
+String GraphicsLayerCA::replayDisplayListAsText(DisplayList::AsTextFlags flags) const
+{
+    auto it = layerDisplayListMap().find(this);
+    if (it != layerDisplayListMap().end()) {
+        TextStream stream;
+        
+        TextStream::GroupScope scope(stream);
+        stream.dumpProperty("clip", it->value.first);
+        stream << it->value.second->asText(flags);
+        return stream.release();
+        
+    }
+
+    return String();
+}
+
 void GraphicsLayerCA::setDebugBackgroundColor(const Color& color)
 {    
     if (color.isValid())
index 2c31253..634e363 100644 (file)
@@ -210,6 +210,9 @@ private:
 
     WEBCORE_EXPORT virtual String displayListAsText(DisplayList::AsTextFlags) const override;
 
+    WEBCORE_EXPORT virtual void setIsTrackingDisplayListReplay(bool) override;
+    WEBCORE_EXPORT virtual String replayDisplayListAsText(DisplayList::AsTextFlags) const override;
+
     WEBCORE_EXPORT virtual double backingStoreMemoryEstimate() const override;
 
     WEBCORE_EXPORT virtual bool shouldRepaintOnSizeChange() const override;
index 9a26a37..4d59f83 100644 (file)
@@ -51,6 +51,7 @@ typedef unsigned AsTextFlags;
 class DisplayList {
     WTF_MAKE_NONCOPYABLE(DisplayList);
     friend class Recorder;
+    friend class Replayer;
 public:
     DisplayList() = default;
     DisplayList(DisplayList&&) = default;
@@ -65,7 +66,7 @@ public:
         ASSERT(index < m_list.size());
         return m_list[index].get();
     }
-    
+
     void clear();
     void removeItemsFromIndex(size_t);
 
@@ -86,6 +87,12 @@ private:
         return m_list.last().get();
     }
 
+    // Less efficient append, only used for tracking replay.
+    void appendItem(Item& item)
+    {
+        m_list.append(item);
+    }
+
     static bool shouldDumpForFlags(AsTextFlags, const Item&);
 
     Vector<Ref<Item>>& list() { return m_list; }
index 2080d81..8cc9154 100644 (file)
@@ -26,7 +26,6 @@
 #include "config.h"
 #include "DisplayListReplayer.h"
 
-#include "DisplayList.h"
 #include "DisplayListItems.h"
 #include "GraphicsContext.h"
 #include "Logging.h"
@@ -45,17 +44,35 @@ Replayer::~Replayer()
 {
 }
 
-void Replayer::replay(const FloatRect& initialClip)
+std::unique_ptr<DisplayList> Replayer::replay(const FloatRect& initialClip, bool trackReplayList)
 {
     LOG_WITH_STREAM(DisplayLists, stream << "\nReplaying with clip " << initialClip);
     UNUSED_PARAM(initialClip);
 
+    std::unique_ptr<DisplayList> replayList;
+    if (UNLIKELY(trackReplayList))
+        replayList = std::make_unique<DisplayList>();
+
     size_t numItems = m_displayList.itemCount();
     for (size_t i = 0; i < numItems; ++i) {
         auto& item = m_displayList.list()[i].get();
-        LOG_WITH_STREAM(DisplayLists, stream << "drawing  " << i << " " << item);
+
+        if (is<DrawingItem>(item)) {
+            const DrawingItem& drawingItem = downcast<DrawingItem>(item);
+            if (drawingItem.extentKnown() && !drawingItem.extent().intersects(initialClip)) {
+                LOG_WITH_STREAM(DisplayLists, stream << "skipping " << i << " " << item);
+                continue;
+            }
+        }
+
+        LOG_WITH_STREAM(DisplayLists, stream << "applying " << i << " " << item);
         item.apply(m_context);
+
+        if (UNLIKELY(trackReplayList))
+            replayList->appendItem(const_cast<Item&>(item));
     }
+    
+    return replayList;
 }
 
 } // namespace DisplayList
index cb2240d..136c15b 100644 (file)
@@ -26,7 +26,9 @@
 #ifndef DisplayListReplayer_h
 #define DisplayListReplayer_h
 
+#include "DisplayList.h"
 #include <wtf/Noncopyable.h>
+#include <wtf/text/WTFString.h>
 
 namespace WebCore {
 
@@ -35,16 +37,14 @@ class GraphicsContext;
 
 namespace DisplayList {
 
-class DisplayList;
-
 class Replayer {
     WTF_MAKE_NONCOPYABLE(Replayer);
 public:
     Replayer(GraphicsContext&, const DisplayList&);
     ~Replayer();
 
-    void replay(const FloatRect& initialClip);
-
+    std::unique_ptr<DisplayList> replay(const FloatRect& initialClip, bool trackReplayList = false);
+    
 private:
     const DisplayList& m_displayList;
     GraphicsContext& m_context;
index df11ca7..2107524 100644 (file)
@@ -198,6 +198,16 @@ String RenderLayerBacking::displayListAsText(DisplayList::AsTextFlags flags) con
     return m_graphicsLayer->displayListAsText(flags);
 }
 
+void RenderLayerBacking::setIsTrackingDisplayListReplay(bool isTrackingReplay)
+{
+    m_graphicsLayer->setIsTrackingDisplayListReplay(isTrackingReplay);
+}
+
+String RenderLayerBacking::replayDisplayListAsText(DisplayList::AsTextFlags flags) const
+{
+    return m_graphicsLayer->replayDisplayListAsText(flags);
+}
+
 void RenderLayerBacking::tiledBackingUsageChanged(const GraphicsLayer* layer, bool usingTiledBacking)
 {
     compositor().layerTiledBackingUsageChanged(layer, usingTiledBacking);
index 7940dff..199af9b 100644 (file)
@@ -245,6 +245,9 @@ public:
     WEBCORE_EXPORT void setUsesDisplayListDrawing(bool);
     WEBCORE_EXPORT String displayListAsText(DisplayList::AsTextFlags) const;
 
+    WEBCORE_EXPORT void setIsTrackingDisplayListReplay(bool);
+    WEBCORE_EXPORT String replayDisplayListAsText(DisplayList::AsTextFlags) const;
+
     LayoutSize devicePixelFractionFromRenderer() const { return m_devicePixelFractionFromRenderer; }
 
 private:
index 5a5082c..a3ac67d 100644 (file)
@@ -1996,6 +1996,28 @@ void Internals::setElementUsesDisplayListDrawing(Element* element, bool usesDisp
     layer->backing()->setUsesDisplayListDrawing(usesDisplayListDrawing);
 }
 
+void Internals::setElementTracksDisplayListReplay(Element* element, bool isTrackingReplay, ExceptionCode& ec)
+{
+    Document* document = contextDocument();
+    if (!document || !document->renderView()) {
+        ec = INVALID_ACCESS_ERR;
+        return;
+    }
+
+    if (!element || !element->renderer() || !element->renderer()->hasLayer()) {
+        ec = INVALID_ACCESS_ERR;
+        return;
+    }
+
+    RenderLayer* layer = downcast<RenderLayerModelObject>(element->renderer())->layer();
+    if (!layer->isComposited()) {
+        ec = INVALID_ACCESS_ERR;
+        return;
+    }
+    
+    layer->backing()->setIsTrackingDisplayListReplay(isTrackingReplay);
+}
+
 String Internals::displayListForElement(Element* element, ExceptionCode& ec)
 {
     return displayListForElement(element, 0, ec);
@@ -2027,6 +2049,37 @@ String Internals::displayListForElement(Element* element, unsigned flags, Except
     return layer->backing()->displayListAsText(displayListFlags);
 }
 
+String Internals::replayDisplayListForElement(Element* element, ExceptionCode& ec)
+{
+    return replayDisplayListForElement(element, 0, ec);
+}
+
+String Internals::replayDisplayListForElement(Element* element, unsigned flags, ExceptionCode& ec)
+{
+    Document* document = contextDocument();
+    if (!document || !document->renderView()) {
+        ec = INVALID_ACCESS_ERR;
+        return String();
+    }
+
+    if (!element || !element->renderer() || !element->renderer()->hasLayer()) {
+        ec = INVALID_ACCESS_ERR;
+        return String();
+    }
+    
+    RenderLayer* layer = downcast<RenderLayerModelObject>(element->renderer())->layer();
+    if (!layer->isComposited()) {
+        ec = INVALID_ACCESS_ERR;
+        return String();
+    }
+
+    DisplayList::AsTextFlags displayListFlags = 0;
+    if (flags & DISPLAY_LIST_INCLUDES_PLATFORM_OPERATIONS)
+        displayListFlags |= DisplayList::AsTextFlag::IncludesPlatformOperations;
+    
+    return layer->backing()->replayDisplayListAsText(displayListFlags);
+}
+
 void Internals::garbageCollectDocumentResources(ExceptionCode& ec) const
 {
     Document* document = contextDocument();
index ec4dbfa..2e75751 100644 (file)
@@ -254,6 +254,7 @@ public:
     RefPtr<ClientRectList> nonFastScrollableRects(ExceptionCode&) const;
 
     void setElementUsesDisplayListDrawing(Element*, bool usesDisplayListDrawing, ExceptionCode&);
+    void setElementTracksDisplayListReplay(Element*, bool isTrackingReplay, ExceptionCode&);
 
     enum {
         // Values need to be kept in sync with Internals.idl.
@@ -262,6 +263,9 @@ public:
     String displayListForElement(Element*, unsigned flags, ExceptionCode&);
     String displayListForElement(Element*, ExceptionCode&);
 
+    String replayDisplayListForElement(Element*, unsigned flags, ExceptionCode&);
+    String replayDisplayListForElement(Element*, ExceptionCode&);
+
     void garbageCollectDocumentResources(ExceptionCode&) const;
 
     void insertAuthorCSS(const String&, ExceptionCode&) const;
index 64400eb..7c6a047 100644 (file)
@@ -226,10 +226,14 @@ enum MediaControlEvent {
 
     // These throw if the element does not have a compositing layer.
     [RaisesException] void setElementUsesDisplayListDrawing(Element element, boolean usesDisplayListDrawing);
+    [RaisesException] void setElementTracksDisplayListReplay(Element element, boolean trackReplay);
 
     // Flags for displayListForElement.
     const unsigned short DISPLAY_LIST_INCLUDES_PLATFORM_OPERATIONS = 1;
+    // Returns the recorded display list.
     [RaisesException] DOMString displayListForElement(Element element, optional unsigned short flags);
+    // Returns the display list that was actually painted.
+    [RaisesException] DOMString replayDisplayListForElement(Element element, optional unsigned short flags);
 
     [RaisesException] void garbageCollectDocumentResources();