Make a way to test display-list drawing
authorsimon.fraser@apple.com <simon.fraser@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 15 Jan 2016 23:57:41 +0000 (23:57 +0000)
committersimon.fraser@apple.com <simon.fraser@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 15 Jan 2016 23:57:41 +0000 (23:57 +0000)
https://bugs.webkit.org/show_bug.cgi?id=152956

Reviewed by Ryosuke Niwa.
Source/WebCore:

Make it possible to toggle display-list drawing for a given compositing
layer via internals, as well as getting a textual representation of the display
list, optionally including items with platform-specific behavior.

Add one test that uses this.

Test: displaylists/layer-dispay-list.html

* platform/graphics/GraphicsLayer.h:
(WebCore::GraphicsLayer::displayListAsText):
* platform/graphics/ca/GraphicsLayerCA.cpp:
(WebCore::GraphicsLayerCA::displayListAsText):
* platform/graphics/ca/GraphicsLayerCA.h:
* platform/graphics/displaylists/DisplayList.cpp:
(WebCore::DisplayList::DisplayList::shouldDumpForFlags):
(WebCore::DisplayList::DisplayList::asText):
* platform/graphics/displaylists/DisplayList.h:
* rendering/RenderLayerBacking.cpp:
(WebCore::RenderLayerBacking::setUsesDisplayListDrawing):
(WebCore::RenderLayerBacking::displayListAsText):
* rendering/RenderLayerBacking.h:
* testing/Internals.cpp:
(WebCore::Internals::setElementUsesDisplayListDrawing):
(WebCore::Internals::displayListForElement):
* testing/Internals.h:
* testing/Internals.idl:

LayoutTests:

Enable displaylists tests on Mac and iOS.

* TestExpectations:
* displaylists/layer-dispay-list-expected.txt: Added.
* displaylists/layer-dispay-list.html: Added.
* platform/ios-simulator/TestExpectations:
* platform/mac/TestExpectations:

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

17 files changed:
LayoutTests/ChangeLog
LayoutTests/TestExpectations
LayoutTests/displaylists/layer-dispay-list-expected.txt [new file with mode: 0644]
LayoutTests/displaylists/layer-dispay-list.html [new file with mode: 0644]
LayoutTests/platform/ios-simulator/TestExpectations
LayoutTests/platform/mac/TestExpectations
Source/WebCore/ChangeLog
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.cpp
Source/WebCore/platform/graphics/displaylists/DisplayList.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 2d26e70..dd613af 100644 (file)
@@ -1,3 +1,18 @@
+2016-01-10  Simon Fraser  <simon.fraser@apple.com>
+
+        Make a way to test display-list drawing
+        https://bugs.webkit.org/show_bug.cgi?id=152956
+
+        Reviewed by Ryosuke Niwa.
+        
+        Enable displaylists tests on Mac and iOS.
+
+        * TestExpectations:
+        * displaylists/layer-dispay-list-expected.txt: Added.
+        * displaylists/layer-dispay-list.html: Added.
+        * platform/ios-simulator/TestExpectations:
+        * platform/mac/TestExpectations:
+
 2016-01-15  Ryosuke Niwa  <rniwa@webkit.org>
 
         createElementNS and createAttributeNS should treat undefined namespaceURI as null string
index ad09d45..1a3f4e9 100644 (file)
@@ -11,6 +11,7 @@ accessibility/ios-simulator [ Skip ]
 accessibility/gtk [ Skip ]
 accessibility/mac [ Skip ]
 accessibility/win [ Skip ]
+displaylists [ Skip ]
 editing/mac [ Skip ]
 editing/pasteboard/gtk [ Skip ]
 tiled-drawing [ Skip ]
diff --git a/LayoutTests/displaylists/layer-dispay-list-expected.txt b/LayoutTests/displaylists/layer-dispay-list-expected.txt
new file mode 100644 (file)
index 0000000..164ec02
--- /dev/null
@@ -0,0 +1,36 @@
+
+(
+  (translate
+    (x 0.00)
+    (y 0.00)))
+(
+  (fill-rect-with-color
+    (extent at (0,0) size 104x104)
+    (rect at (0,0) size 104x104)
+    (color #008000)))
+(
+  (set-state
+    (change-flags 131456)
+    (fill-color #0000FF)
+    (stroke-style 0)
+    (should-antialias 0)))
+(
+  (draw-rect
+    (extent at (0,0) size 104x2)
+    (rect at (0,0) size 104x2)
+    (border-thickness 1.00)))
+(
+  (draw-rect
+    (extent at (0,102) size 104x2)
+    (rect at (0,102) size 104x2)
+    (border-thickness 1.00)))
+(
+  (draw-rect
+    (extent at (0,0) size 2x104)
+    (rect at (0,0) size 2x104)
+    (border-thickness 1.00)))
+(
+  (draw-rect
+    (extent at (102,0) size 2x104)
+    (rect at (102,0) size 2x104)
+    (border-thickness 1.00)))
diff --git a/LayoutTests/displaylists/layer-dispay-list.html b/LayoutTests/displaylists/layer-dispay-list.html
new file mode 100644 (file)
index 0000000..c791aa2
--- /dev/null
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+
+<html>
+<head>
+    <style>
+        .box {
+            width: 100px;
+            height: 100px;
+            background-color: green;
+            border: 2px solid blue;
+        }
+        
+        .composited {
+            -webkit-transform: translateZ(0);
+        }
+    </style>
+    <script>
+        if (window.testRunner) {
+            testRunner.dumpAsText();
+            testRunner.waitUntilDone();
+        }
+
+        var targetDiv;
+        function doTest()
+        {
+            // document.body.offsetWidth;
+            targetDiv = document.getElementById('target');
+            if (window.internals)
+                internals.setElementUsesDisplayListDrawing(targetDiv, true);
+            
+            window.setTimeout(function() {
+                if (window.internals) {
+                    var displayList = internals.displayListForElement(targetDiv);
+                    document.getElementById('output').textContent = displayList;
+                }
+                if (window.testRunner)
+                    testRunner.notifyDone();
+            }, 0);
+        }
+        window.addEventListener('load', doTest, false);
+    </script>
+</head>
+<body>
+<div id="target" class="composited box">
+</div>
+<pre id="output"></pre>
+</body>
+</html>
index 5a0cb11..b8d005a 100644 (file)
@@ -7,6 +7,7 @@
 #//////////////////////////////////////////////////////////////////////////////////////////
 
 accessibility/ios-simulator [ Pass ]
+displaylists [ Pass ]
 quicklook [ Pass ]
 http/tests/quicklook [ Pass ]
 
index 36470e1..7734647 100644 (file)
@@ -7,6 +7,7 @@
 #//////////////////////////////////////////////////////////////////////////////////////////
 
 accessibility/mac [ Pass ]
+displaylists [ Pass ]
 editing/mac [ Pass ]
 fast/scrolling/latching [ Pass ]
 
index 6ebf566..61225b5 100644 (file)
@@ -1,3 +1,37 @@
+2016-01-10  Simon Fraser  <simon.fraser@apple.com>
+
+        Make a way to test display-list drawing
+        https://bugs.webkit.org/show_bug.cgi?id=152956
+
+        Reviewed by Ryosuke Niwa.
+
+        Make it possible to toggle display-list drawing for a given compositing
+        layer via internals, as well as getting a textual representation of the display
+        list, optionally including items with platform-specific behavior.
+        
+        Add one test that uses this.
+
+        Test: displaylists/layer-dispay-list.html
+
+        * platform/graphics/GraphicsLayer.h:
+        (WebCore::GraphicsLayer::displayListAsText):
+        * platform/graphics/ca/GraphicsLayerCA.cpp:
+        (WebCore::GraphicsLayerCA::displayListAsText):
+        * platform/graphics/ca/GraphicsLayerCA.h:
+        * platform/graphics/displaylists/DisplayList.cpp:
+        (WebCore::DisplayList::DisplayList::shouldDumpForFlags):
+        (WebCore::DisplayList::DisplayList::asText):
+        * platform/graphics/displaylists/DisplayList.h:
+        * rendering/RenderLayerBacking.cpp:
+        (WebCore::RenderLayerBacking::setUsesDisplayListDrawing):
+        (WebCore::RenderLayerBacking::displayListAsText):
+        * rendering/RenderLayerBacking.h:
+        * testing/Internals.cpp:
+        (WebCore::Internals::setElementUsesDisplayListDrawing):
+        (WebCore::Internals::displayListForElement):
+        * testing/Internals.h:
+        * testing/Internals.idl:
+
 2016-01-15  Olivier Blin  <olivier.blin@softathome.com>
 
         Fix audio build with video disabled
index 72c6678..f26f883 100644 (file)
@@ -54,6 +54,10 @@ class TiledBacking;
 class TimingFunction;
 class TransformationMatrix;
 
+namespace DisplayList {
+typedef unsigned AsTextFlags;
+}
+
 // Base class for animation values (also used for transitions). Here to
 // represent values for properties being animated via the GraphicsLayer,
 // without pulling in style-related data from outside of the platform directory.
@@ -517,6 +521,9 @@ public:
     // pointers for the layers and timing data will be included in the returned string.
     WEBCORE_EXPORT String layerTreeAsText(LayerTreeAsTextBehavior = LayerTreeAsTextBehaviorNormal) const;
 
+    // For testing.
+    WEBCORE_EXPORT virtual String displayListAsText(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;
 
index 4d28544..0ff644b 100644 (file)
@@ -3270,6 +3270,14 @@ void GraphicsLayerCA::setShowRepaintCounter(bool showCounter)
     noteLayerPropertyChanged(DebugIndicatorsChanged);
 }
 
+String GraphicsLayerCA::displayListAsText(DisplayList::AsTextFlags flags) const
+{
+    if (!m_displayList)
+        return String();
+
+    return m_displayList->asText(flags);
+}
+
 void GraphicsLayerCA::setDebugBackgroundColor(const Color& color)
 {    
     if (color.isValid())
index 95a226e..2c31253 100644 (file)
@@ -208,6 +208,8 @@ private:
     WEBCORE_EXPORT virtual void setIsViewportConstrained(bool) override;
     virtual bool isViewportConstrained() const override { return m_isViewportConstrained; }
 
+    WEBCORE_EXPORT virtual String displayListAsText(DisplayList::AsTextFlags) const override;
+
     WEBCORE_EXPORT virtual double backingStoreMemoryEstimate() const override;
 
     WEBCORE_EXPORT virtual bool shouldRepaintOnSizeChange() const override;
index fb9fd30..3aa5400 100644 (file)
@@ -58,6 +58,51 @@ void DisplayList::removeItemsFromIndex(size_t index)
     m_list.resize(index);
 }
 
+bool DisplayList::shouldDumpForFlags(AsTextFlags flags, const Item& item)
+{
+    switch (item.type()) {
+    case ItemType::SetState:
+        if (!(flags & AsTextFlag::IncludesPlatformOperations)) {
+            const auto& stateItem = downcast<SetState>(item);
+            // FIXME: for now, only drop the item if the only state-change flags are platform-specific.
+            if (stateItem.state().m_changeFlags == GraphicsContextState::ShouldSubpixelQuantizeFontsChange)
+                return false;
+
+            if (stateItem.state().m_changeFlags == GraphicsContextState::AntialiasedFontDilationEnabledChange)
+                return false;
+
+            if (stateItem.state().m_changeFlags == GraphicsContextState::ShouldSubpixelQuantizeFontsChange)
+                return false;
+        }
+        break;
+#if USE(CG)
+    case ItemType::ApplyFillPattern:
+    case ItemType::ApplyStrokePattern:
+        if (!(flags & AsTextFlag::IncludesPlatformOperations))
+            return false;
+        break;
+#endif
+    default:
+        break;
+    }
+    return true;
+}
+
+String DisplayList::asText(AsTextFlags flags) const
+{
+    TextStream stream;
+    size_t numItems = m_list.size();
+    for (size_t i = 0; i < numItems; ++i) {
+        const auto& item = m_list[i].get();
+        if (!shouldDumpForFlags(flags, item))
+            continue;
+
+        TextStream::GroupScope scope(stream);
+        stream << item;
+    }
+    return stream.release();
+}
+
 void DisplayList::dump(TextStream& ts) const
 {
     TextStream::GroupScope group(ts);
index 643bd24..9a26a37 100644 (file)
@@ -41,6 +41,13 @@ namespace DisplayList {
 
 class Item;
 
+enum AsTextFlag {
+    None                            = 0,
+    IncludesPlatformOperations      = 1 << 0,
+};
+
+typedef unsigned AsTextFlags;
+
 class DisplayList {
     WTF_MAKE_NONCOPYABLE(DisplayList);
     friend class Recorder;
@@ -64,6 +71,8 @@ public:
 
     size_t itemCount() const { return m_list.size(); }
     size_t sizeInBytes() const;
+    
+    String asText(AsTextFlags) const;
 
 #if !defined(NDEBUG) || !LOG_DISABLED
     WTF::CString description() const;
@@ -77,6 +86,8 @@ private:
         return m_list.last().get();
     }
 
+    static bool shouldDumpForFlags(AsTextFlags, const Item&);
+
     Vector<Ref<Item>>& list() { return m_list; }
 
     Vector<Ref<Item>> m_list;
index 76943d6..df11ca7 100644 (file)
@@ -182,6 +182,22 @@ std::unique_ptr<GraphicsLayer> RenderLayerBacking::createGraphicsLayer(const Str
     return graphicsLayer;
 }
 
+void RenderLayerBacking::setUsesDisplayListDrawing(bool usesDisplayListDrawing)
+{
+    // Note that this only affects the primary layer.
+    if (usesDisplayListDrawing == m_graphicsLayer->usesDisplayListDrawing())
+        return;
+
+    m_graphicsLayer->setUsesDisplayListDrawing(usesDisplayListDrawing);
+    if (m_graphicsLayer->drawsContent())
+        m_graphicsLayer->setNeedsDisplay();
+}
+
+String RenderLayerBacking::displayListAsText(DisplayList::AsTextFlags flags) const
+{
+    return m_graphicsLayer->displayListAsText(flags);
+}
+
 void RenderLayerBacking::tiledBackingUsageChanged(const GraphicsLayer* layer, bool usingTiledBacking)
 {
     compositor().layerTiledBackingUsageChanged(layer, usingTiledBacking);
index 60c1ca8..7940dff 100644 (file)
@@ -240,6 +240,10 @@ public:
 
     // Return an estimate of the backing store area (in pixels) allocated by this object's GraphicsLayers.
     WEBCORE_EXPORT double backingStoreMemoryEstimate() const;
+    
+    // For testing only.
+    WEBCORE_EXPORT void setUsesDisplayListDrawing(bool);
+    WEBCORE_EXPORT String displayListAsText(DisplayList::AsTextFlags) const;
 
     LayoutSize devicePixelFractionFromRenderer() const { return m_devicePixelFractionFromRenderer; }
 
index d00306f..994d11e 100644 (file)
@@ -43,6 +43,7 @@
 #include "DOMPath.h"
 #include "DOMStringList.h"
 #include "DOMWindow.h"
+#include "DisplayList.h"
 #include "Document.h"
 #include "DocumentMarker.h"
 #include "DocumentMarkerController.h"
@@ -94,6 +95,7 @@
 #include "PseudoElement.h"
 #include "Range.h"
 #include "RenderEmbeddedObject.h"
+#include "RenderLayerBacking.h"
 #include "RenderLayerCompositor.h"
 #include "RenderMenuList.h"
 #include "RenderTreeAsText.h"
@@ -1973,6 +1975,59 @@ RefPtr<ClientRectList> Internals::nonFastScrollableRects(ExceptionCode& ec) cons
     return page->nonFastScrollableRects();
 }
 
+void Internals::setElementUsesDisplayListDrawing(Element* element, bool usesDisplayListDrawing, 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()->setUsesDisplayListDrawing(usesDisplayListDrawing);
+}
+
+String Internals::displayListForElement(Element* element, ExceptionCode& ec)
+{
+    return displayListForElement(element, 0, ec);
+}
+
+String Internals::displayListForElement(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()->displayListAsText(displayListFlags);
+}
+
 void Internals::garbageCollectDocumentResources(ExceptionCode& ec) const
 {
     Document* document = contextDocument();
index e81ac3a..b4ee127 100644 (file)
@@ -253,6 +253,15 @@ public:
     String mainThreadScrollingReasons(ExceptionCode&) const;
     RefPtr<ClientRectList> nonFastScrollableRects(ExceptionCode&) const;
 
+    void setElementUsesDisplayListDrawing(Element*, bool usesDisplayListDrawing, ExceptionCode&);
+
+    enum {
+        // Values need to be kept in sync with Internals.idl.
+        DISPLAY_LIST_INCLUDES_PLATFORM_OPERATIONS = 1,
+    };
+    String displayListForElement(Element*, unsigned flags, ExceptionCode&);
+    String displayListForElement(Element*, ExceptionCode&);
+
     void garbageCollectDocumentResources(ExceptionCode&) const;
 
     void allowRoundingHacks() const;
index 0f51553..643aee2 100644 (file)
@@ -224,6 +224,13 @@ enum MediaControlEvent {
 
     [RaisesException] DOMString repaintRectsAsText();
 
+    // These throw if the element does not have a compositing layer.
+    [RaisesException] void setElementUsesDisplayListDrawing(Element element, boolean usesDisplayListDrawing);
+
+    // Flags for displayListForElement.
+    const unsigned short DISPLAY_LIST_INCLUDES_PLATFORM_OPERATIONS = 1;
+    [RaisesException] DOMString displayListForElement(Element element, optional unsigned short flags);
+
     [RaisesException] void garbageCollectDocumentResources();
 
     void allowRoundingHacks();