Paint invalidation tests for slimming paint v2

Add a new type of paint invalidation test for slimming paint v2.

- They are reftests, to check the correctness of painted result;
- Tracks paint invalidation objects and checks them against expected
  list.

This CL converts two paint/invalidation tests into the new style.

Will convert some fast/repaint and compositing/repaint tests into this
style for spv2 after this CL. The original tests are not suitable for
spv2 because
- it's hard to determine if a test is actually failing or needs
  rebaseline for spv2;
- they don't cover correctness of paint results.

BUG=524134

Review URL: https://codereview.chromium.org/1324763002

git-svn-id: svn://svn.chromium.org/blink/trunk@201565 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent f1394fcc
# We tests under paint/invalidation/spv2 as --enable-slimming-paint-v2 physical suite.
crbug.com/524134 virtual/spv2/paint/invalidation/spv2 [ Skip ]
# TODO(wangxianzhu): Triage the failures
crbug.com/524134 virtual/spv2/compositing/repaint/opacity-between-absolute.html [ ImageOnlyFailure ]
......@@ -57,6 +59,7 @@ crbug.com/524236 virtual/spv2/compositing/repaint/should-not-repaint-composited-
crbug.com/524236 virtual/spv2/compositing/repaint/should-not-repaint-composited-transform.html [ Failure ]
crbug.com/524236 virtual/spv2/compositing/repaint/should-not-repaint-composited-z-index.html [ Failure ]
crbug.com/524236 virtual/spv2/fast/repaint/absolute-layer-specified-left-or-right-auto-width-moved-vertically.html [ Failure ]
crbug.com/524236 paint/invalidation/spv2/invalidate-after-composited-scroll.html [ ImageOnlyFailure ]
crbug.com/504613 crbug.com/524248 paint/images/image-backgrounds-not-antialiased.html [ Skip ]
crbug.com/504613 crbug.com/524248 virtual/spv2/paint/images/image-backgrounds-not-antialiased.html [ Skip ]
......
<!doctype HTML>
<div id="scroller" style="overflow:auto; will-change: transform; width: 200px; height: 200px; position: absolute; left: 300px; top: 300px;">
<div>
<div class="spacer" style="width: 1px; height: 2400px;"></div>
<div id="target" style="width: 100px; height: 100px; background: papayawhip"></div>
<div class="spacer" style="width: 1px; height: 2400px;"></div>
</div>
</div>
Tests that invalidation of a div after scrolling invalidates just the div and scrollbars, and no other area.
<script>
scroller.scrollTop = 2350;
</script>
\ No newline at end of file
<!doctype HTML>
<div>
<div class="spacer" style="width: 1px; height: 2400px;"></div>
<div id="target" style="width: 100px; height: 100px; background: papayawhip"></div>
<div class="spacer" style="width: 1px; height: 2400px;"></div>
</div>
Tests that invalidation of a div after scrolling invalidates just the div and no other area.
<script>
window.scrollBy(0, 2350);
</script>
\ No newline at end of file
<!-- Based on paint/invalidation/invalidate-after-composited-scroll-of-window.html -->
<!doctype HTML>
<div>
<div class="spacer" style="width: 1px; height: 2400px;"></div>
<div id="target" style="width: 100px; height: 100px; background: blue"></div>
<div class="spacer" style="width: 1px; height: 2400px;"></div>
</div>
<script src="resources/paint-invalidation-test.js"></script>
Tests that invalidation of a div after scrolling invalidates just the div and no other area.
<script>
window.expectedPaintInvalidationObjects = [
"LayoutBlockFlow DIV id='target'",
];
function paintInvalidationTest() {
window.scrollBy(0, 2350);
target.style.background = "papayawhip";
}
onload = runPaintInvalidationTest;
</script>
<!-- Based on paint/invalidation/invalidate-after-composited-scroll.html -->
<!doctype HTML>
<div id="scroller" style="overflow:auto; will-change: transform; width: 200px; height: 200px; position: absolute; left: 300px; top: 300px;">
<div>
<div class="spacer" style="width: 1px; height: 2400px;"></div>
<div id="target" style="width: 100px; height: 100px; background: blue"></div>
<div class="spacer" style="width: 1px; height: 2400px;"></div>
</div>
</div>
<script src="resources/paint-invalidation-test.js"></script>
Tests that invalidation of a div after scrolling invalidates just the div and scrollbars, and no other area.
<script>
window.expectedPaintInvalidationObjects = [
"LayoutBlockFlow DIV id='target'",
];
function paintInvalidationTest() {
scroller.scrollTop = 2350;
target.style.background = "papayawhip";
}
onload = runPaintInvalidationTest;
</script>
\ No newline at end of file
// Asynchronous tests should manually call finishPaintInvalidationTest at the appropriate time.
window.testIsAsync = false;
// All paint invalidation tests are asynchronous from test-runner's point of view.
if (window.testRunner)
testRunner.waitUntilDone();
function runPaintInvalidationTest()
{
if (!window.testRunner || !window.internals) {
setTimeout(paintInvalidationTest, 500);
return;
}
// TODO(enne): this is a workaround for multiple svg onload events.
// See: http://crbug.com/372946
if (window.hasRunPaintInvalidationTest)
return;
window.hasRunPaintInvalidationTest = true;
testRunner.layoutAndPaintAsyncThen(function()
{
window.internals.startTrackingPaintInvalidationObjects();
paintInvalidationTest();
if (!window.testIsAsync)
finishPaintInvalidationTest();
});
}
function removeAllChildren(element)
{
while (element.firstChild)
element.removeChild(element.firstChild);
}
function finishPaintInvalidationTest()
{
if (!window.testRunner || !window.internals)
return;
testRunner.layoutAndPaintAsyncThen(function()
{
document.body.offsetTop;
var paintInvalidationObjects = JSON.stringify(internals.trackedPaintInvalidationObjects());
var expectedPaintInvalidationObjects = JSON.stringify(window.expectedPaintInvalidationObjects);
internals.stopTrackingPaintInvalidationObjects();
if (paintInvalidationObjects != expectedPaintInvalidationObjects) {
var message = 'Paint invalidation objects mismatch.'
+ '\nExpected:\n' + expectedPaintInvalidationObjects.replace(/","/g, '",\n "')
+ '\nActual:\n' + paintInvalidationObjects.replace(/","/g, '",\n "');
testRunner.logToStderr(message);
while (document.body.firstChild)
document.body.removeChild(document.body.firstChild);
var pre = document.createElement('pre');
pre.appendChild(document.createTextNode('(To copy results as text, see stderr.)\n\n' + message));
document.body.appendChild(pre);
}
testRunner.notifyDone();
});
}
setTimeout(function() {
testRunner.notifyDone();
}, 2000);
\ No newline at end of file
......@@ -1974,6 +1974,24 @@ void Internals::forceFullRepaint(Document* document, ExceptionState& exceptionSt
layoutView->invalidatePaintForViewAndCompositedLayers();
}
void Internals::startTrackingPaintInvalidationObjects()
{
ASSERT(RuntimeEnabledFeatures::slimmingPaintV2Enabled());
toLocalFrame(frame()->page()->mainFrame())->view()->layoutView()->layer()->graphicsLayerBacking()->displayItemList()->startTrackingPaintInvalidationObjects();
}
void Internals::stopTrackingPaintInvalidationObjects()
{
ASSERT(RuntimeEnabledFeatures::slimmingPaintV2Enabled());
toLocalFrame(frame()->page()->mainFrame())->view()->layoutView()->layer()->graphicsLayerBacking()->displayItemList()->stopTrackingPaintInvalidationObjects();
}
Vector<String> Internals::trackedPaintInvalidationObjects()
{
ASSERT(RuntimeEnabledFeatures::slimmingPaintV2Enabled());
return toLocalFrame(frame()->page()->mainFrame())->view()->layoutView()->layer()->graphicsLayerBacking()->displayItemList()->trackedPaintInvalidationObjects();
}
ClientRectList* Internals::draggableRegions(Document* document, ExceptionState& exceptionState)
{
return annotatedRegions(document, true, exceptionState);
......
......@@ -282,6 +282,10 @@ public:
void updateLayoutIgnorePendingStylesheetsAndRunPostLayoutTasks(Node*, ExceptionState&);
void forceFullRepaint(Document*, ExceptionState&);
void startTrackingPaintInvalidationObjects();
void stopTrackingPaintInvalidationObjects();
Vector<String> trackedPaintInvalidationObjects();
ClientRectList* draggableRegions(Document*, ExceptionState&);
ClientRectList* nonDraggableRegions(Document*, ExceptionState&);
......
......@@ -230,8 +230,9 @@
DOMString[] getReferencedFilePaths();
// These functions both reset the tracked repaint rects. They are inteded to be used in the following order:
// startTrackingRepaints, repaintRectsAsText, stopTrackingRepaints.
// These functions both reset the tracked repaint rects. They are intended to be used in the following order:
// startTrackingRepaints(), repaintRectsAsText(), stopTrackingRepaints().
// TODO(wangxianzhu): Remove these functions when we no longer use repaint rects.
[RaisesException, TypeChecking=Interface] void startTrackingRepaints(Document document);
[RaisesException, TypeChecking=Interface] void stopTrackingRepaints(Document document);
......@@ -242,6 +243,16 @@
[RaisesException, TypeChecking=Interface] void forceFullRepaint(Document document);
// These functions both reset the tracked paint invalidation objects. They are intended to be used in the following order:
// startTrackingPaintInvalidationObjects(), trackedPaintInvalidationObjects(), stopTrackingPaintInvalidationObjects().
void startTrackingPaintInvalidationObjects();
void stopTrackingPaintInvalidationObjects();
// Returns a list of debug strings for objects that were invalidated between
// startTrackingPaintInvalidationObjects() and stopTrackingPaintInvalidationObjects().
// If an object is invalidated multiple times, it will appear in the list multiple times.
DOMString[] trackedPaintInvalidationObjects();
// Returns a list of draggable/non-draggable regions in the document.
[RaisesException, TypeChecking=Interface] ClientRectList draggableRegions(Document document);
[RaisesException, TypeChecking=Interface] ClientRectList nonDraggableRegions(Document document);
......
......@@ -64,6 +64,7 @@
namespace blink {
// TODO(wangxianzhu): Remove this when we no longer invalidate rects.
struct PaintInvalidationTrackingInfo {
Vector<FloatRect> invalidationRects;
Vector<String> invalidationObjects;
......@@ -785,7 +786,7 @@ void GraphicsLayer::setSize(const FloatSize& size)
// The red debug fill needs to be invalidated if the layer resizes.
if (m_displayItemList) {
ASSERT(RuntimeEnabledFeatures::slimmingPaintEnabled());
m_displayItemList->invalidate(displayItemClient());
m_displayItemList->invalidateUntracked(displayItemClient());
}
#endif
}
......@@ -986,7 +987,7 @@ void GraphicsLayer::setNeedsDisplayInRect(const IntRect& rect, PaintInvalidation
void GraphicsLayer::invalidateDisplayItemClient(const DisplayItemClientWrapper& displayItemClient)
{
ASSERT(RuntimeEnabledFeatures::slimmingPaintEnabled());
displayItemList()->invalidate(displayItemClient.displayItemClient());
displayItemList()->invalidate(displayItemClient);
if (isTrackingPaintInvalidations())
trackPaintInvalidationObject(displayItemClient.debugName());
}
......
......@@ -6,7 +6,6 @@
#include "platform/graphics/paint/DisplayItemList.h"
#include "platform/NotImplemented.h"
#include "platform/RuntimeEnabledFeatures.h"
#include "platform/TraceEvent.h"
#include "platform/graphics/paint/DrawingDisplayItem.h"
......@@ -112,7 +111,15 @@ void DisplayItemList::endScope()
endSkippingCache();
}
void DisplayItemList::invalidate(DisplayItemClient client)
void DisplayItemList::invalidate(const DisplayItemClientWrapper& client)
{
invalidateUntracked(client.displayItemClient());
if (RuntimeEnabledFeatures::slimmingPaintV2Enabled() && m_trackedPaintInvalidationObjects)
m_trackedPaintInvalidationObjects->append(client.debugName());
}
void DisplayItemList::invalidateUntracked(DisplayItemClient client)
{
ASSERT(RuntimeEnabledFeatures::slimmingPaintEnabled());
// Can only be called during layout/paintInvalidation, not during painting.
......@@ -129,6 +136,9 @@ void DisplayItemList::invalidateAll()
m_currentDisplayItems.clear();
m_validlyCachedClients.clear();
m_validlyCachedClientsDirty = false;
if (RuntimeEnabledFeatures::slimmingPaintV2Enabled() && m_trackedPaintInvalidationObjects)
m_trackedPaintInvalidationObjects->append("##ALL##");
}
bool DisplayItemList::clientCacheIsValid(DisplayItemClient client) const
......
......@@ -6,6 +6,7 @@
#define DisplayItemList_h
#include "platform/PlatformExport.h"
#include "platform/RuntimeEnabledFeatures.h"
#include "platform/graphics/ContiguousContainer.h"
#include "platform/graphics/paint/DisplayItem.h"
#include "platform/graphics/paint/Transform3DDisplayItem.h"
......@@ -43,7 +44,8 @@ public:
}
// These methods are called during paint invalidation.
void invalidate(DisplayItemClient);
void invalidate(const DisplayItemClientWrapper&);
void invalidateUntracked(DisplayItemClient);
void invalidateAll();
// These methods are called during painting.
......@@ -109,6 +111,22 @@ public:
void showDebugData() const;
#endif
void startTrackingPaintInvalidationObjects()
{
ASSERT(RuntimeEnabledFeatures::slimmingPaintV2Enabled());
m_trackedPaintInvalidationObjects = adoptPtr(new Vector<String>());
}
void stopTrackingPaintInvalidationObjects()
{
ASSERT(RuntimeEnabledFeatures::slimmingPaintV2Enabled());
m_trackedPaintInvalidationObjects = nullptr;
}
Vector<String> trackedPaintInvalidationObjects()
{
ASSERT(RuntimeEnabledFeatures::slimmingPaintV2Enabled());
return m_trackedPaintInvalidationObjects ? *m_trackedPaintInvalidationObjects : Vector<String>();
}
protected:
DisplayItemList()
: m_currentDisplayItems(kMaximumDisplayItemSize, 0)
......@@ -183,6 +201,8 @@ private:
// the duplicated ids are from.
DisplayItemIndicesByClientMap m_newDisplayItemIndicesByClient;
#endif
OwnPtr<Vector<String>> m_trackedPaintInvalidationObjects;
};
} // namespace blink
......
......@@ -133,7 +133,7 @@ TEST_F(DisplayItemListTest, UpdateBasic)
TestDisplayItem(second, backgroundDrawingType),
TestDisplayItem(first, foregroundDrawingType));
displayItemList().invalidate(second.displayItemClient());
displayItemList().invalidate(second);
drawRect(context, first, backgroundDrawingType, FloatRect(100, 100, 300, 300));
drawRect(context, first, foregroundDrawingType, FloatRect(100, 100, 300, 300));
displayItemList().commitNewDisplayItems();
......@@ -160,7 +160,7 @@ TEST_F(DisplayItemListTest, UpdateSwapOrder)
TestDisplayItem(second, backgroundDrawingType),
TestDisplayItem(unaffected, backgroundDrawingType));
displayItemList().invalidate(second.displayItemClient());
displayItemList().invalidate(second);
drawRect(context, second, backgroundDrawingType, FloatRect(100, 100, 50, 200));
drawRect(context, first, backgroundDrawingType, FloatRect(100, 100, 100, 100));
drawRect(context, unaffected, backgroundDrawingType, FloatRect(300, 300, 10, 10));
......@@ -221,7 +221,7 @@ TEST_F(DisplayItemListTest, UpdateInvalidationWithPhases)
TestDisplayItem(second, foregroundDrawingType),
TestDisplayItem(third, foregroundDrawingType));
displayItemList().invalidate(second.displayItemClient());
displayItemList().invalidate(second);
drawRect(context, first, backgroundDrawingType, FloatRect(100, 100, 100, 100));
drawRect(context, second, backgroundDrawingType, FloatRect(100, 100, 50, 200));
drawRect(context, third, backgroundDrawingType, FloatRect(300, 100, 50, 50));
......@@ -253,8 +253,8 @@ TEST_F(DisplayItemListTest, UpdateAddFirstOverlap)
TestDisplayItem(second, backgroundDrawingType),
TestDisplayItem(second, foregroundDrawingType));
displayItemList().invalidate(first.displayItemClient());
displayItemList().invalidate(second.displayItemClient());
displayItemList().invalidate(first);
displayItemList().invalidate(second);
drawRect(context, first, backgroundDrawingType, FloatRect(100, 100, 150, 150));
drawRect(context, first, foregroundDrawingType, FloatRect(100, 100, 150, 150));
drawRect(context, second, backgroundDrawingType, FloatRect(200, 200, 50, 50));
......@@ -267,7 +267,7 @@ TEST_F(DisplayItemListTest, UpdateAddFirstOverlap)
TestDisplayItem(second, backgroundDrawingType),
TestDisplayItem(second, foregroundDrawingType));
displayItemList().invalidate(first.displayItemClient());
displayItemList().invalidate(first);
drawRect(context, second, backgroundDrawingType, FloatRect(200, 200, 50, 50));
drawRect(context, second, foregroundDrawingType, FloatRect(200, 200, 50, 50));
displayItemList().commitNewDisplayItems();
......@@ -291,8 +291,8 @@ TEST_F(DisplayItemListTest, UpdateAddLastOverlap)
TestDisplayItem(first, backgroundDrawingType),
TestDisplayItem(first, foregroundDrawingType));
displayItemList().invalidate(first.displayItemClient());
displayItemList().invalidate(second.displayItemClient());
displayItemList().invalidate(first);
displayItemList().invalidate(second);
drawRect(context, first, backgroundDrawingType, FloatRect(100, 100, 150, 150));
drawRect(context, first, foregroundDrawingType, FloatRect(100, 100, 150, 150));
drawRect(context, second, backgroundDrawingType, FloatRect(200, 200, 50, 50));
......@@ -305,8 +305,8 @@ TEST_F(DisplayItemListTest, UpdateAddLastOverlap)
TestDisplayItem(second, backgroundDrawingType),
TestDisplayItem(second, foregroundDrawingType));
displayItemList().invalidate(first.displayItemClient());
displayItemList().invalidate(second.displayItemClient());
displayItemList().invalidate(first);
displayItemList().invalidate(second);
drawRect(context, first, backgroundDrawingType, FloatRect(100, 100, 150, 150));
drawRect(context, first, foregroundDrawingType, FloatRect(100, 100, 150, 150));
displayItemList().commitNewDisplayItems();
......@@ -335,7 +335,7 @@ TEST_F(DisplayItemListTest, UpdateClip)
TestDisplayItem(second, backgroundDrawingType),
TestDisplayItem(first, DisplayItem::clipTypeToEndClipType(clipType)));
displayItemList().invalidate(first.displayItemClient());
displayItemList().invalidate(first);
drawRect(context, first, backgroundDrawingType, FloatRect(100, 100, 150, 150));
drawRect(context, second, backgroundDrawingType, FloatRect(100, 100, 150, 150));
displayItemList().commitNewDisplayItems();
......@@ -344,7 +344,7 @@ TEST_F(DisplayItemListTest, UpdateClip)
TestDisplayItem(first, backgroundDrawingType),
TestDisplayItem(second, backgroundDrawingType));
displayItemList().invalidate(second.displayItemClient());
displayItemList().invalidate(second);
drawRect(context, first, backgroundDrawingType, FloatRect(100, 100, 150, 150));
{
ClipRecorder clipRecorder(context, second, clipType, LayoutRect(1, 1, 2, 2));
......@@ -377,7 +377,7 @@ TEST_F(DisplayItemListTest, CachedDisplayItems)
const SkPicture* firstPicture = static_cast<const DrawingDisplayItem&>(displayItemList().displayItems()[0]).picture();
const SkPicture* secondPicture = static_cast<const DrawingDisplayItem&>(displayItemList().displayItems()[1]).picture();
displayItemList().invalidate(first.displayItemClient());
displayItemList().invalidate(first);
EXPECT_FALSE(displayItemList().clientCacheIsValid(first.displayItemClient()));
EXPECT_TRUE(displayItemList().clientCacheIsValid(second.displayItemClient()));
......@@ -429,7 +429,7 @@ TEST_F(DisplayItemListTest, ComplexUpdateSwapOrder)
TestDisplayItem(container2, foregroundDrawingType));
// Simulate the situation when container1 e.g. gets a z-index that is now greater than container2.
displayItemList().invalidate(container1.displayItemClient());
displayItemList().invalidate(container1);
drawRect(context, container2, backgroundDrawingType, FloatRect(100, 200, 100, 100));
drawRect(context, content2, backgroundDrawingType, FloatRect(100, 200, 50, 200));
drawRect(context, content2, foregroundDrawingType, FloatRect(100, 200, 50, 200));
......@@ -562,12 +562,12 @@ TEST_F(DisplayItemListTest, CachedNestedSubsequenceUpdate)
TestDisplayItem(container2, DisplayItem::EndSubsequence));
// Invalidate container1 but not content1.
displayItemList().invalidate(container1.displayItemClient());
displayItemList().invalidate(container1);
// Container2 itself now becomes empty (but still has the 'content2' child),
// and chooses not to output subsequence info.
displayItemList().invalidate(container2.displayItemClient());
displayItemList().invalidate(content2.displayItemClient());
displayItemList().invalidate(container2);
displayItemList().invalidate(content2);
EXPECT_FALSE(SubsequenceRecorder::useCachedSubsequenceIfPossible(context, container2));
EXPECT_FALSE(SubsequenceRecorder::useCachedSubsequenceIfPossible(context, content2));
// Content2 now outputs foreground only.
......@@ -661,7 +661,7 @@ TEST_F(DisplayItemListTest, Scope)
EXPECT_NE(picture2, static_cast<const DrawingDisplayItem&>(displayItemList().displayItems()[2]).picture());
// Now the multicol becomes 3 columns and repaints.
displayItemList().invalidate(multicol.displayItemClient());
displayItemList().invalidate(multicol);
drawRect(context, multicol, backgroundDrawingType, FloatRect(100, 100, 100, 100));
displayItemList().beginScope();
......@@ -714,7 +714,7 @@ TEST_F(DisplayItemListTest, OptimizeNoopPairs)
TestDisplayItem(second, DisplayItem::EndClipPath),
TestDisplayItem(third, backgroundDrawingType));
displayItemList().invalidate(second.displayItemClient());
displayItemList().invalidate(second);
drawRect(context, first, backgroundDrawingType, FloatRect(0, 0, 100, 100));
{
ClipRecorder clipRecorder(context, second, clipType, LayoutRect(1, 1, 2, 2));
......@@ -728,7 +728,7 @@ TEST_F(DisplayItemListTest, OptimizeNoopPairs)
TestDisplayItem(first, backgroundDrawingType),
TestDisplayItem(third, backgroundDrawingType));
displayItemList().invalidate(second.displayItemClient());
displayItemList().invalidate(second);
drawRect(context, first, backgroundDrawingType, FloatRect(0, 0, 100, 100));
{
ClipRecorder clipRecorder(context, second, clipType, LayoutRect(1, 1, 2, 2));
......
......@@ -1589,6 +1589,7 @@ class Port(object):
# For example, to turn on force-compositing-mode in the svg/ directory:
# PhysicalTestSuite('svg', ['--force-compositing-mode']),
PhysicalTestSuite('fast/text', ["--enable-direct-write", "--enable-font-antialiasing"]),
PhysicalTestSuite('paint/invalidation/spv2', ['--enable-slimming-paint-v2'])
]
def virtual_test_suites(self):
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment