- Revision
- 181941
- Author
- [email protected]
- Date
- 2015-03-25 03:02:37 -0700 (Wed, 25 Mar 2015)
Log Message
Merge r181710 - Avoid repaints when changing transform on an element with multiple background images
https://bugs.webkit.org/show_bug.cgi?id=142841
Reviewed by Zalan Bujtas.
Source/WebCore:
Replace the cheap test for changed images in RenderElement::updateFillImages()
with an exhaustive test that walks the entire list of background images,
since any ensuing repaint is way more expensive than a slightly more expensive check here.
Test: fast/repaint/multiple-backgrounds-style-change.html
* rendering/RenderElement.cpp:
(WebCore::RenderElement::updateFillImages):
* rendering/style/FillLayer.cpp:
(WebCore::layerImagesIdentical): See if both images are the same (either none
or both mask images, and same image pointer).
(WebCore::FillLayer::imagesIdentical): Walk the two FillLayer lists, checking the images
on each one. Returns false if we reach the end of one list before the other, or the images
are different.
* rendering/style/FillLayer.h: New static function; static because
it compares two FillLayer lists, and I think that makes more sense than
a member function.
LayoutTests:
Test that changes transform on a composited element with 2 background images,
and tests for no repaints.
* fast/repaint/multiple-backgrounds-style-change-expected.txt: Added.
* fast/repaint/multiple-backgrounds-style-change.html: Added.
Modified Paths
Added Paths
Diff
Modified: releases/WebKitGTK/webkit-2.8/LayoutTests/ChangeLog (181940 => 181941)
--- releases/WebKitGTK/webkit-2.8/LayoutTests/ChangeLog 2015-03-25 09:53:47 UTC (rev 181940)
+++ releases/WebKitGTK/webkit-2.8/LayoutTests/ChangeLog 2015-03-25 10:02:37 UTC (rev 181941)
@@ -1,3 +1,16 @@
+2015-03-18 Simon Fraser <[email protected]>
+
+ Avoid repaints when changing transform on an element with multiple background images
+ https://bugs.webkit.org/show_bug.cgi?id=142841
+
+ Reviewed by Zalan Bujtas.
+
+ Test that changes transform on a composited element with 2 background images,
+ and tests for no repaints.
+
+ * fast/repaint/multiple-backgrounds-style-change-expected.txt: Added.
+ * fast/repaint/multiple-backgrounds-style-change.html: Added.
+
2015-03-18 Manuel Rego Casasnovas <[email protected]>
Flex and grid items should be painted as inline-blocks
Added: releases/WebKitGTK/webkit-2.8/LayoutTests/fast/repaint/multiple-backgrounds-style-change-expected.txt (0 => 181941)
--- releases/WebKitGTK/webkit-2.8/LayoutTests/fast/repaint/multiple-backgrounds-style-change-expected.txt (rev 0)
+++ releases/WebKitGTK/webkit-2.8/LayoutTests/fast/repaint/multiple-backgrounds-style-change-expected.txt 2015-03-25 10:02:37 UTC (rev 181941)
@@ -0,0 +1,10 @@
+Tests that a transform change on an element with multiple background images doesn't cause a repaint.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS layerTreeAsText.indexOf('(repaint rects') == -1 is true
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: releases/WebKitGTK/webkit-2.8/LayoutTests/fast/repaint/multiple-backgrounds-style-change.html (0 => 181941)
--- releases/WebKitGTK/webkit-2.8/LayoutTests/fast/repaint/multiple-backgrounds-style-change.html (rev 0)
+++ releases/WebKitGTK/webkit-2.8/LayoutTests/fast/repaint/multiple-backgrounds-style-change.html 2015-03-25 10:02:37 UTC (rev 181941)
@@ -0,0 +1,74 @@
+<html>
+<head>
+ <style>
+ .box {
+ height: 200px;
+ width: 200px;
+ border: 1px solid black;
+ background-repeat: no-repeat;
+ background-size: 100px 100px;
+ background-position: 0 0, 100px 100px;
+ }
+
+ .apply-images {
+ background-image: url('../images/resources/green-256x256.jpg'), url('../images/resources/dice.png');
+ }
+
+ .composited {
+ -webkit-transform: translate3d(0, 0, 0);
+ }
+
+ .composited.changed {
+ -webkit-transform: translate3d(50px, 50px, 0);
+ }
+ </style>
+<script>jsTestIsAsync = true;</script>
+<script src=""
+<script>
+ description("Tests that a transform change on an element with multiple background images doesn't cause a repaint.");
+ function startTrackingRepaints()
+ {
+ if (window.internals)
+ window.internals.startTrackingRepaints();
+ document.getElementById('test').classList.add('changed');
+ setTimeout(logRepaints, 0)
+ }
+
+ function logRepaints()
+ {
+ layerTreeAsText = window.internals.layerTreeAsText(document, internals.LAYER_TREE_INCLUDES_REPAINT_RECTS);
+ window.internals.stopTrackingRepaints();
+ shouldBeTrue("layerTreeAsText.indexOf('(repaint rects') == -1");
+
+ finishJSTest();
+ }
+
+ var loadedRemaining = 2;
+ function imageLoaded()
+ {
+ if (!--loadedRemaining) {
+ document.getElementById('test').classList.add('apply-images');
+ setTimeout(startTrackingRepaints, 0);
+ }
+ }
+
+ function doTest()
+ {
+ // We have to know that the images to be used by CSS are loaded to avoid spurious repaints later.
+ var firstImage = new Image();
+ firstImage._onload_ = imageLoaded;
+ firstImage.src = '';
+
+ var secondImage = new Image();
+ secondImage._onload_ = imageLoaded;
+ secondImage.src = '';
+ }
+
+ window.addEventListener('load', doTest, false);
+</script>
+</head>
+<body>
+ <div id="test" class="composited box">
+ </div>
+<script src=""
+</html>
Modified: releases/WebKitGTK/webkit-2.8/Source/WebCore/ChangeLog (181940 => 181941)
--- releases/WebKitGTK/webkit-2.8/Source/WebCore/ChangeLog 2015-03-25 09:53:47 UTC (rev 181940)
+++ releases/WebKitGTK/webkit-2.8/Source/WebCore/ChangeLog 2015-03-25 10:02:37 UTC (rev 181941)
@@ -1,3 +1,28 @@
+2015-03-18 Simon Fraser <[email protected]>
+
+ Avoid repaints when changing transform on an element with multiple background images
+ https://bugs.webkit.org/show_bug.cgi?id=142841
+
+ Reviewed by Zalan Bujtas.
+
+ Replace the cheap test for changed images in RenderElement::updateFillImages()
+ with an exhaustive test that walks the entire list of background images,
+ since any ensuing repaint is way more expensive than a slightly more expensive check here.
+
+ Test: fast/repaint/multiple-backgrounds-style-change.html
+
+ * rendering/RenderElement.cpp:
+ (WebCore::RenderElement::updateFillImages):
+ * rendering/style/FillLayer.cpp:
+ (WebCore::layerImagesIdentical): See if both images are the same (either none
+ or both mask images, and same image pointer).
+ (WebCore::FillLayer::imagesIdentical): Walk the two FillLayer lists, checking the images
+ on each one. Returns false if we reach the end of one list before the other, or the images
+ are different.
+ * rendering/style/FillLayer.h: New static function; static because
+ it compares two FillLayer lists, and I think that makes more sense than
+ a member function.
+
2015-03-18 Anders Carlsson <[email protected]>
Pass cookies by reference in CookieHash functions
Modified: releases/WebKitGTK/webkit-2.8/Source/WebCore/rendering/RenderElement.cpp (181940 => 181941)
--- releases/WebKitGTK/webkit-2.8/Source/WebCore/rendering/RenderElement.cpp 2015-03-25 09:53:47 UTC (rev 181940)
+++ releases/WebKitGTK/webkit-2.8/Source/WebCore/rendering/RenderElement.cpp 2015-03-25 10:02:37 UTC (rev 181941)
@@ -330,7 +330,7 @@
void RenderElement::updateFillImages(const FillLayer* oldLayers, const FillLayer* newLayers)
{
// Optimize the common case
- if (oldLayers && !oldLayers->next() && newLayers && !newLayers->next() && oldLayers->image() == newLayers->image() && oldLayers->maskImage() == newLayers->maskImage())
+ if (FillLayer::imagesIdentical(oldLayers, newLayers))
return;
// Go through the new layers and addClients first, to avoid removing all clients of an image.
Modified: releases/WebKitGTK/webkit-2.8/Source/WebCore/rendering/style/FillLayer.cpp (181940 => 181941)
--- releases/WebKitGTK/webkit-2.8/Source/WebCore/rendering/style/FillLayer.cpp 2015-03-25 09:53:47 UTC (rev 181940)
+++ releases/WebKitGTK/webkit-2.8/Source/WebCore/rendering/style/FillLayer.cpp 2015-03-25 10:02:37 UTC (rev 181941)
@@ -392,4 +392,20 @@
return false;
}
+static inline bool layerImagesIdentical(const FillLayer& layer1, const FillLayer& layer2)
+{
+ // We just care about pointer equivalency.
+ return layer1.hasMaskImage() == layer2.hasMaskImage() && layer1.image() == layer2.image();
+}
+
+bool FillLayer::imagesIdentical(const FillLayer* layer1, const FillLayer* layer2)
+{
+ for (; layer1 && layer2; layer1 = layer1->next(), layer2 = layer2->next()) {
+ if (!layerImagesIdentical(*layer1, *layer2))
+ return false;
+ }
+
+ return !layer1 && !layer2;
+}
+
} // namespace WebCore
Modified: releases/WebKitGTK/webkit-2.8/Source/WebCore/rendering/style/FillLayer.h (181940 => 181941)
--- releases/WebKitGTK/webkit-2.8/Source/WebCore/rendering/style/FillLayer.h 2015-03-25 09:53:47 UTC (rev 181940)
+++ releases/WebKitGTK/webkit-2.8/Source/WebCore/rendering/style/FillLayer.h 2015-03-25 10:02:37 UTC (rev 181941)
@@ -159,6 +159,8 @@
void fillUnsetProperties();
void cullEmptyLayers();
+ static bool imagesIdentical(const FillLayer*, const FillLayer*);
+
static EFillAttachment initialFillAttachment(EFillLayerType) { return ScrollBackgroundAttachment; }
static EFillBox initialFillClip(EFillLayerType) { return BorderFillBox; }
static EFillBox initialFillOrigin(EFillLayerType type) { return type == BackgroundFillLayer ? PaddingFillBox : BorderFillBox; }