REGRESSION (iOS 12.2): CSS perspective property value can only be set correctly once
authorsimon.fraser@apple.com <simon.fraser@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 24 Apr 2019 21:26:52 +0000 (21:26 +0000)
committersimon.fraser@apple.com <simon.fraser@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 24 Apr 2019 21:26:52 +0000 (21:26 +0000)
https://bugs.webkit.org/show_bug.cgi?id=197105
Source/WebCore:

rdar://problem/50068230

Reviewed by Zalan Bujtas.

Make sure we trigger a geometry update when style properties change that
result in a StyleDifference::RecompositeLayer, and which are updated on layers
via RenderLayerBacking::updateGeometry().

Tests: compositing/style-change/backface-visibility-change.html
       compositing/style-change/perspective-change.html
       compositing/style-change/perspective-origin-change.html
       compositing/style-change/transform-origin-change.html
       compositing/style-change/transform-style-change.html

* rendering/RenderLayerCompositor.cpp:
(WebCore::recompositeChangeRequiresGeometryUpdate):
(WebCore::RenderLayerCompositor::layerStyleChanged):

LayoutTests:

Reviewed by Zalan Bujtas.

* compositing/style-change/backface-visibility-change-expected.html: Added.
* compositing/style-change/backface-visibility-change.html: Added.
* compositing/style-change/perspective-change-expected.html: Added.
* compositing/style-change/perspective-change.html: Added.
* compositing/style-change/perspective-origin-change-expected.html: Added.
* compositing/style-change/perspective-origin-change.html: Added.
* compositing/style-change/transform-origin-change-expected.html: Added.
* compositing/style-change/transform-origin-change.html: Added.
* compositing/style-change/transform-style-change-expected.html: Added.
* compositing/style-change/transform-style-change.html: Added.

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

13 files changed:
LayoutTests/ChangeLog
LayoutTests/compositing/style-change/backface-visibility-change-expected.html [new file with mode: 0644]
LayoutTests/compositing/style-change/backface-visibility-change.html [new file with mode: 0644]
LayoutTests/compositing/style-change/perspective-change-expected.html [new file with mode: 0644]
LayoutTests/compositing/style-change/perspective-change.html [new file with mode: 0644]
LayoutTests/compositing/style-change/perspective-origin-change-expected.html [new file with mode: 0644]
LayoutTests/compositing/style-change/perspective-origin-change.html [new file with mode: 0644]
LayoutTests/compositing/style-change/transform-origin-change-expected.html [new file with mode: 0644]
LayoutTests/compositing/style-change/transform-origin-change.html [new file with mode: 0644]
LayoutTests/compositing/style-change/transform-style-change-expected.html [new file with mode: 0644]
LayoutTests/compositing/style-change/transform-style-change.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/rendering/RenderLayerCompositor.cpp

index 35be3f4..abe3d64 100644 (file)
@@ -1,5 +1,23 @@
 2019-04-24  Simon Fraser  <simon.fraser@apple.com>
 
+        REGRESSION (iOS 12.2): CSS perspective property value can only be set correctly once
+        https://bugs.webkit.org/show_bug.cgi?id=197105
+
+        Reviewed by Zalan Bujtas.
+
+        * compositing/style-change/backface-visibility-change-expected.html: Added.
+        * compositing/style-change/backface-visibility-change.html: Added.
+        * compositing/style-change/perspective-change-expected.html: Added.
+        * compositing/style-change/perspective-change.html: Added.
+        * compositing/style-change/perspective-origin-change-expected.html: Added.
+        * compositing/style-change/perspective-origin-change.html: Added.
+        * compositing/style-change/transform-origin-change-expected.html: Added.
+        * compositing/style-change/transform-origin-change.html: Added.
+        * compositing/style-change/transform-style-change-expected.html: Added.
+        * compositing/style-change/transform-style-change.html: Added.
+
+2019-04-24  Simon Fraser  <simon.fraser@apple.com>
+
         Make it possible to control the renderTreeAsText output by setting options on testRunner
         https://bugs.webkit.org/show_bug.cgi?id=197133
 
diff --git a/LayoutTests/compositing/style-change/backface-visibility-change-expected.html b/LayoutTests/compositing/style-change/backface-visibility-change-expected.html
new file mode 100644 (file)
index 0000000..a1bdfbf
--- /dev/null
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <style>
+        .container {
+            margin: 50px;
+            height: 300px;
+            width: 300px;
+            border: 1px solid black;
+            perspective: 500px;
+        }
+        
+        .transformed {
+            width: 100%;
+            height: 100%;
+            background-color: blue;
+            transform: rotateY(145deg);
+            -webkit-backface-visibility: visible;
+        }
+    </style>
+</head>
+<body>
+    <div class="container">
+        <div class="transformed"></div>
+    </div>
+</body>
+</html>
diff --git a/LayoutTests/compositing/style-change/backface-visibility-change.html b/LayoutTests/compositing/style-change/backface-visibility-change.html
new file mode 100644 (file)
index 0000000..c3273b2
--- /dev/null
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <style>
+        .container {
+            margin: 50px;
+            height: 300px;
+            width: 300px;
+            border: 1px solid black;
+            perspective: 500px;
+        }
+        
+        .transformed {
+            width: 100%;
+            height: 100%;
+            background-color: blue;
+            transform: rotateY(145deg);
+            -webkit-backface-visibility: hidden;
+        }
+
+        .transformed.changed {
+            -webkit-backface-visibility: visible;
+        }
+    </style>
+    <script>
+        if (window.testRunner)
+            testRunner.waitUntilDone();
+
+        window.addEventListener('load', () => {
+            setTimeout(() => {
+                document.querySelector('.transformed').classList.add('changed');
+                if (window.testRunner)
+                    testRunner.notifyDone();
+            }, 1000);
+            
+        }, false);
+    </script>
+</head>
+<body>
+    <div class="container">
+        <div class="transformed"></div>
+    </div>
+</body>
+</html>
diff --git a/LayoutTests/compositing/style-change/perspective-change-expected.html b/LayoutTests/compositing/style-change/perspective-change-expected.html
new file mode 100644 (file)
index 0000000..a54e47b
--- /dev/null
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <style>
+        .container {
+            margin: 50px;
+            height: 300px;
+            width: 300px;
+            border: 1px solid black;
+            perspective: 1500px;
+        }
+        
+        .transformed {
+            width: 100%;
+            height: 100%;
+            transform: rotateY(45deg);
+            background-color: blue;
+        }
+    </style>
+</head>
+<body>
+    <div class="container">
+        <div class="transformed"></div>
+    </div>
+</body>
+</html>
diff --git a/LayoutTests/compositing/style-change/perspective-change.html b/LayoutTests/compositing/style-change/perspective-change.html
new file mode 100644 (file)
index 0000000..784d774
--- /dev/null
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <style>
+        .container {
+            margin: 50px;
+            height: 300px;
+            width: 300px;
+            border: 1px solid black;
+            perspective: 500px;
+        }
+        
+        .container.changed {
+            perspective: 1500px;
+        }
+        
+        .transformed {
+            width: 100%;
+            height: 100%;
+            transform: rotateY(45deg);
+            background-color: blue;
+        }
+        
+        .transformed:hover {
+            transform-origin: top left;
+            background-color: orange;
+        }
+    </style>
+    <script>
+        if (window.testRunner)
+            testRunner.waitUntilDone();
+
+        window.addEventListener('load', () => {
+            setTimeout(() => {
+                document.querySelector('.container').classList.add('changed');
+                if (window.testRunner)
+                    testRunner.notifyDone();
+            }, 0);
+            
+        }, false);
+    </script>
+</head>
+<body>
+    <div class="container">
+        <div class="transformed"></div>
+    </div>
+</body>
+</html>
diff --git a/LayoutTests/compositing/style-change/perspective-origin-change-expected.html b/LayoutTests/compositing/style-change/perspective-origin-change-expected.html
new file mode 100644 (file)
index 0000000..216a2c8
--- /dev/null
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <style>
+        .container {
+            margin: 50px;
+            height: 300px;
+            width: 300px;
+            border: 1px solid black;
+            perspective: 500px;
+            perspective-origin: top left;
+        }
+        
+        .transformed {
+            width: 100%;
+            height: 100%;
+            transform: rotateY(45deg);
+            background-color: blue;
+        }
+    </style>
+</head>
+<body>
+    <div class="container">
+        <div class="transformed"></div>
+    </div>
+</body>
+</html>
diff --git a/LayoutTests/compositing/style-change/perspective-origin-change.html b/LayoutTests/compositing/style-change/perspective-origin-change.html
new file mode 100644 (file)
index 0000000..bd72dbf
--- /dev/null
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <style>
+        .container {
+            margin: 50px;
+            height: 300px;
+            width: 300px;
+            border: 1px solid black;
+            perspective: 500px;
+        }
+        
+        .container.changed {
+            perspective-origin: top left;
+        }
+
+        .transformed {
+            width: 100%;
+            height: 100%;
+            transform: rotateY(45deg);
+            background-color: blue;
+        }
+    </style>
+    <script>
+        if (window.testRunner)
+            testRunner.waitUntilDone();
+
+        window.addEventListener('load', () => {
+            setTimeout(() => {
+                document.querySelector('.container').classList.add('changed');
+                if (window.testRunner)
+                    testRunner.notifyDone();
+            }, 0);
+            
+        }, false);
+    </script>
+</head>
+<body>
+    <div class="container">
+        <div class="transformed"></div>
+    </div>
+</body>
+</html>
diff --git a/LayoutTests/compositing/style-change/transform-origin-change-expected.html b/LayoutTests/compositing/style-change/transform-origin-change-expected.html
new file mode 100644 (file)
index 0000000..e452b5a
--- /dev/null
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <style>
+        .container {
+            margin: 50px;
+            height: 300px;
+            width: 300px;
+            border: 1px solid black;
+        }
+        
+        .transformed {
+            width: 100%;
+            height: 100%;
+            background-color: blue;
+            transform: rotateY(45deg);
+            transform-origin: top left;
+        }
+    </style>
+</head>
+<body>
+    <div class="container">
+        <div class="transformed"></div>
+    </div>
+</body>
+</html>
diff --git a/LayoutTests/compositing/style-change/transform-origin-change.html b/LayoutTests/compositing/style-change/transform-origin-change.html
new file mode 100644 (file)
index 0000000..c86d483
--- /dev/null
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <style>
+        .container {
+            margin: 50px;
+            height: 300px;
+            width: 300px;
+            border: 1px solid black;
+        }
+        
+        .transformed {
+            width: 100%;
+            height: 100%;
+            background-color: blue;
+            transform: rotateY(45deg);
+        }
+        
+        .transformed.changed {
+            transform-origin: top left;
+        }
+    </style>
+    <script>
+        if (window.testRunner)
+            testRunner.waitUntilDone();
+
+        window.addEventListener('load', () => {
+            setTimeout(() => {
+                document.querySelector('.transformed').classList.add('changed');
+                if (window.testRunner)
+                    testRunner.notifyDone();
+            }, 0);
+            
+        }, false);
+    </script>
+</head>
+<body>
+    <div class="container">
+        <div class="transformed"></div>
+    </div>
+</body>
+</html>
diff --git a/LayoutTests/compositing/style-change/transform-style-change-expected.html b/LayoutTests/compositing/style-change/transform-style-change-expected.html
new file mode 100644 (file)
index 0000000..a01d5b3
--- /dev/null
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <style>
+        .container {
+            margin: 50px;
+            height: 300px;
+            width: 300px;
+            border: 1px solid black;
+            perspective: 500px;
+        }
+        
+        .intermediate {
+            width: 100%;
+            height: 100%;
+            transform: translateX(0);
+            transform-style: preserve-3d;
+        }
+        
+        .transformed {
+            width: 100%;
+            height: 100%;
+            background-color: blue;
+            transform: rotateY(45deg);
+        }
+    </style>
+</head>
+<body>
+    <div class="container">
+        <div class="intermediate">
+            <div class="transformed"></div>
+        </div>
+    </div>
+</body>
+</html>
diff --git a/LayoutTests/compositing/style-change/transform-style-change.html b/LayoutTests/compositing/style-change/transform-style-change.html
new file mode 100644 (file)
index 0000000..371d7c5
--- /dev/null
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <style>
+        .container {
+            margin: 50px;
+            height: 300px;
+            width: 300px;
+            border: 1px solid black;
+            perspective: 500px;
+        }
+        
+        .intermediate {
+            width: 100%;
+            height: 100%;
+            transform: translateX(0);
+            transform-style: flat;
+        }
+        
+        .intermediate.changed {
+            transform-style: preserve-3d;
+        }
+        
+        .transformed {
+            width: 100%;
+            height: 100%;
+            background-color: blue;
+            transform: rotateY(45deg);
+        }
+    </style>
+    <script>
+        if (window.testRunner)
+            testRunner.waitUntilDone();
+
+        window.addEventListener('load', () => {
+            setTimeout(() => {
+                document.querySelector('.intermediate').classList.add('changed');
+                if (window.testRunner)
+                    testRunner.notifyDone();
+            }, 0);
+            
+        }, false);
+    </script>
+</head>
+<body>
+    <div class="container">
+        <div class="intermediate">
+            <div class="transformed"></div>
+        </div>
+    </div>
+</body>
+</html>
index 6e9bbe1..4e0bc60 100644 (file)
@@ -1,5 +1,27 @@
 2019-04-24  Simon Fraser  <simon.fraser@apple.com>
 
+        REGRESSION (iOS 12.2): CSS perspective property value can only be set correctly once
+        https://bugs.webkit.org/show_bug.cgi?id=197105
+        rdar://problem/50068230
+
+        Reviewed by Zalan Bujtas.
+
+        Make sure we trigger a geometry update when style properties change that
+        result in a StyleDifference::RecompositeLayer, and which are updated on layers
+        via RenderLayerBacking::updateGeometry().
+
+        Tests: compositing/style-change/backface-visibility-change.html
+               compositing/style-change/perspective-change.html
+               compositing/style-change/perspective-origin-change.html
+               compositing/style-change/transform-origin-change.html
+               compositing/style-change/transform-style-change.html
+
+        * rendering/RenderLayerCompositor.cpp:
+        (WebCore::recompositeChangeRequiresGeometryUpdate):
+        (WebCore::RenderLayerCompositor::layerStyleChanged):
+
+2019-04-24  Simon Fraser  <simon.fraser@apple.com>
+
         Make it possible to control the renderTreeAsText output by setting options on testRunner
         https://bugs.webkit.org/show_bug.cgi?id=197133
 
index 1a1b2aa..0f2c4b1 100644 (file)
@@ -1414,6 +1414,19 @@ static bool styleAffectsLayerGeometry(const RenderStyle& style)
     return style.hasClip() || style.clipPath() || style.hasBorderRadius();
 }
 
+static bool recompositeChangeRequiresGeometryUpdate(const RenderStyle& oldStyle, const RenderStyle& newStyle)
+{
+    return oldStyle.transform() != newStyle.transform()
+        || oldStyle.transformOriginX() != newStyle.transformOriginX()
+        || oldStyle.transformOriginY() != newStyle.transformOriginY()
+        || oldStyle.transformOriginZ() != newStyle.transformOriginZ()
+        || oldStyle.transformStyle3D() != newStyle.transformStyle3D()
+        || oldStyle.perspective() != newStyle.perspective()
+        || oldStyle.perspectiveOriginX() != newStyle.perspectiveOriginX()
+        || oldStyle.perspectiveOriginY() != newStyle.perspectiveOriginY()
+        || oldStyle.backfaceVisibility() != newStyle.backfaceVisibility();
+}
+
 void RenderLayerCompositor::layerStyleChanged(StyleDifference diff, RenderLayer& layer, const RenderStyle* oldStyle)
 {
     if (diff == StyleDifference::Equal)
@@ -1467,12 +1480,10 @@ void RenderLayerCompositor::layerStyleChanged(StyleDifference diff, RenderLayer&
     if (diff == StyleDifference::RecompositeLayer && layer.isComposited() && is<RenderWidget>(layer.renderer()))
         layer.setNeedsCompositingConfigurationUpdate();
 
-    if (diff >= StyleDifference::RecompositeLayer && oldStyle) {
-        if (oldStyle->transform() != newStyle.transform()) {
-            // FIXME: transform changes really need to trigger layout. See RenderElement::adjustStyleDifference().
-            layer.setNeedsPostLayoutCompositingUpdate();
-            layer.setNeedsCompositingGeometryUpdate();
-        }
+    if (diff >= StyleDifference::RecompositeLayer && oldStyle && recompositeChangeRequiresGeometryUpdate(*oldStyle, newStyle)) {
+        // FIXME: transform changes really need to trigger layout. See RenderElement::adjustStyleDifference().
+        layer.setNeedsPostLayoutCompositingUpdate();
+        layer.setNeedsCompositingGeometryUpdate();
     }
 
     if (diff >= StyleDifference::Layout) {