Have will-change create stacking context when necessary
authorsimon.fraser@apple.com <simon.fraser@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 15 Aug 2015 20:13:24 +0000 (20:13 +0000)
committersimon.fraser@apple.com <simon.fraser@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 15 Aug 2015 20:13:24 +0000 (20:13 +0000)
https://bugs.webkit.org/show_bug.cgi?id=148060

Reviewed by Zalan Bujtas.

Source/WebCore:

If will-change includes a property whose non-initial value can create
stacking context, create stacking context for that element.

Test: fast/css/will-change/will-change-creates-stacking-context.html

* css/StyleResolver.cpp:
(WebCore::StyleResolver::adjustRenderStyle):
* rendering/style/RenderStyle.h: Add willChangeCreatesStackingContext(),
which on most cases is a fast, inlined 'return false'. Otherwise ask
the WillChangeData.
* rendering/style/WillChangeData.cpp:
(WebCore::propertyCreatesStackingContext):
(WebCore::WillChangeData::createsStackingContext):
* rendering/style/WillChangeData.h:

LayoutTests:

Ref test for will-change creating stacking context.

* fast/css/will-change/resources/will-change-stacking-helper.js: Added.
(makeStackingBlock):
* fast/css/will-change/will-change-creates-stacking-context-expected.html: Added.
* fast/css/will-change/will-change-creates-stacking-context.html: Added.
* platform/efl/TestExpectations: Mark image failure on EFL, since some CSS
properties in the test are disabled there.

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

LayoutTests/ChangeLog
LayoutTests/fast/css/will-change/resources/will-change-stacking-helper.js [new file with mode: 0644]
LayoutTests/fast/css/will-change/will-change-creates-stacking-context-expected.html [new file with mode: 0644]
LayoutTests/fast/css/will-change/will-change-creates-stacking-context.html [new file with mode: 0644]
LayoutTests/platform/efl/TestExpectations
LayoutTests/platform/mac-mavericks/TestExpectations
Source/WebCore/ChangeLog
Source/WebCore/css/StyleResolver.cpp
Source/WebCore/rendering/style/RenderStyle.h
Source/WebCore/rendering/style/WillChangeData.cpp
Source/WebCore/rendering/style/WillChangeData.h

index 2d362d1..c92fd12 100644 (file)
@@ -1,3 +1,19 @@
+2015-08-15  Simon Fraser  <simon.fraser@apple.com>
+
+        Have will-change create stacking context when necessary
+        https://bugs.webkit.org/show_bug.cgi?id=148060
+
+        Reviewed by Zalan Bujtas.
+        
+        Ref test for will-change creating stacking context.
+
+        * fast/css/will-change/resources/will-change-stacking-helper.js: Added.
+        (makeStackingBlock):
+        * fast/css/will-change/will-change-creates-stacking-context-expected.html: Added.
+        * fast/css/will-change/will-change-creates-stacking-context.html: Added.
+        * platform/efl/TestExpectations: Mark image failure on EFL, since some CSS
+        properties in the test are disabled there.
+
 2015-08-14  Simon Fraser  <simon.fraser@apple.com>
 
         Implement parsing for CSS will-change
diff --git a/LayoutTests/fast/css/will-change/resources/will-change-stacking-helper.js b/LayoutTests/fast/css/will-change/resources/will-change-stacking-helper.js
new file mode 100644 (file)
index 0000000..84da1d9
--- /dev/null
@@ -0,0 +1,51 @@
+var willChangeValues = [
+    { 'property' : 'auto', 'stacking' : false },
+    { 'property' : 'background', 'stacking' : false },
+    { 'property' : 'will-change', 'stacking' : false },
+
+    { 'property' : 'clip-path', 'stacking' : true },
+    { 'property' : 'mask', 'stacking' : true },
+    { 'property' : 'opacity', 'stacking' : true },
+    { 'property' : 'position', 'stacking' : true },
+    { 'property' : 'z-index', 'stacking' : true },
+    { 'property' : 'mix-blend-mode', 'stacking' : true },
+    { 'property' : 'isolation', 'stacking' : true },
+    { 'property' : 'perspective', 'stacking' : true },
+    { 'property' : 'transform', 'stacking' : true },
+    { 'property' : 'transform-style', 'stacking' : true },
+
+    { 'property' : '-webkit-filter', 'stacking' : true },
+    { 'property' : '-webkit-clip-path', 'stacking' : true },
+    { 'property' : '-webkit-backface-visibility', 'stacking' : true },
+    { 'property' : '-webkit-box-reflect', 'stacking' : true },
+    { 'property' : '-webkit-backdrop-filter', 'stacking' : true },
+    { 'property' : '-webkit-mask', 'stacking' : true },
+    { 'property' : '-webkit-mask-image', 'stacking' : true },
+    { 'property' : '-webkit-mask-box-image', 'stacking' : true },
+    { 'property' : '-webkit-transform', 'stacking' : true },
+    { 'property' : '-webkit-transform-style', 'stacking' : true },
+    { 'property' : '-webkit-flow-from', 'stacking' : true },
+];
+
+function makeStackingBlock(stackingProperty, value)
+{
+    var container = document.createElement('div');
+    container.className = 'container';
+
+    var potentialStackingContext = document.createElement('div');
+    potentialStackingContext.className = 'potential-stacking-context';
+    potentialStackingContext.style[stackingProperty] = value;
+
+    var child = document.createElement('div');
+    child.className = 'child';
+    potentialStackingContext.appendChild(child);
+
+    container.appendChild(potentialStackingContext);
+
+    var interposer = document.createElement('div');
+    interposer.className = 'interposer';
+    container.appendChild(interposer);
+    
+    document.body.appendChild(container);
+}
+
diff --git a/LayoutTests/fast/css/will-change/will-change-creates-stacking-context-expected.html b/LayoutTests/fast/css/will-change/will-change-creates-stacking-context-expected.html
new file mode 100644 (file)
index 0000000..c277a5d
--- /dev/null
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+
+<html>
+<head>
+    <style>
+        .container {
+            display: inline-block;
+            margin: 25px;
+            width: 50px;
+            height: 50px;
+            position: relative;
+            border: 1px solid black;
+        }
+        
+        .container div {
+            width: 100%;
+            height: 100%;
+        }
+        
+        .potential-stacking-context {
+            position: relative;
+            z-index: auto;
+            background-color: silver;
+        }
+        
+        .child {
+            position: absolute;
+            top: 10px;
+            left: 10px;
+            z-index: 1;
+            background-color: orange;
+        }
+
+        .interposer {
+            position: absolute;
+            top: 20px;
+            left: 20px;
+            z-index: 0;
+            background-color: green;
+        }
+    </style>
+
+    <script src="resources/will-change-stacking-helper.js"></script>
+    <script>
+        function doTest()
+        {
+            for (value of willChangeValues) {
+                makeStackingBlock('z-index', value.stacking ? '0' : 'auto');
+            }
+        }
+        
+        window.addEventListener('load', doTest, false);
+    </script>
+</head>
+<body>
+</body>
+</html>
diff --git a/LayoutTests/fast/css/will-change/will-change-creates-stacking-context.html b/LayoutTests/fast/css/will-change/will-change-creates-stacking-context.html
new file mode 100644 (file)
index 0000000..0e48ac6
--- /dev/null
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+
+<html>
+<head>
+    <style>
+        .container {
+            display: inline-block;
+            margin: 25px;
+            width: 50px;
+            height: 50px;
+            position: relative;
+            border: 1px solid black;
+        }
+        
+        .container div {
+            width: 100%;
+            height: 100%;
+        }
+        
+        .potential-stacking-context {
+            position: relative;
+            z-index: auto;
+            background-color: silver;
+        }
+        
+        .child {
+            position: absolute;
+            top: 10px;
+            left: 10px;
+            z-index: 1;
+            background-color: orange;
+        }
+
+        .interposer {
+            position: absolute;
+            top: 20px;
+            left: 20px;
+            z-index: 0;
+            background-color: green;
+        }
+    </style>
+
+    <script src="resources/will-change-stacking-helper.js"></script>
+    <script>
+        function doTest()
+        {
+            for (value of willChangeValues) {
+                makeStackingBlock('will-change', value.property);
+            }
+        }
+        
+        window.addEventListener('load', doTest, false);
+    </script>
+</head>
+<body>
+</body>
+</html>
index 2f2ee7d..30f8f6c 100644 (file)
@@ -404,6 +404,9 @@ webkit.org/b/85465 compositing/filters [ Skip ]
 # CSS image-resolution is not yet enabled.
 webkit.org/b/85262 fast/css/image-resolution
 
+# Some CSS properties not supported on EFL
+fast/css/will-change/will-change-creates-stacking-context.html [ ImageOnlyFailure ]
+
 # Perf tests are really slow in debug builds and there are few benefits in running them.
 [ Debug ] perf [ WontFix ]
 
index 56b9686..f0e3ce1 100644 (file)
@@ -9,6 +9,7 @@ fast/events/mouse-force-up.html [ Skip ]
 # No support for Filters Level 2
 compositing/media-controls-bar-appearance.html [ Skip ]
 compositing/media-controls-bar-appearance-big.html [ Skip ]
+fast/css/will-change/will-change-creates-stacking-context.html [ ImageOnlyFailure ]
 
 # No support for non-HLS Media Selection Group
 media/accessiblity-describes-video.html [ Skip ]
index f704bc9..9f8d6a0 100644 (file)
@@ -1,3 +1,25 @@
+2015-08-15  Simon Fraser  <simon.fraser@apple.com>
+
+        Have will-change create stacking context when necessary
+        https://bugs.webkit.org/show_bug.cgi?id=148060
+
+        Reviewed by Zalan Bujtas.
+        
+        If will-change includes a property whose non-initial value can create
+        stacking context, create stacking context for that element.
+
+        Test: fast/css/will-change/will-change-creates-stacking-context.html
+
+        * css/StyleResolver.cpp:
+        (WebCore::StyleResolver::adjustRenderStyle):
+        * rendering/style/RenderStyle.h: Add willChangeCreatesStackingContext(),
+        which on most cases is a fast, inlined 'return false'. Otherwise ask
+        the WillChangeData.
+        * rendering/style/WillChangeData.cpp:
+        (WebCore::propertyCreatesStackingContext):
+        (WebCore::WillChangeData::createsStackingContext):
+        * rendering/style/WillChangeData.h:
+
 2015-08-15  Commit Queue  <commit-queue@webkit.org>
 
         Unreviewed, rolling out r188508.
index 4673c85..1356b6f 100644 (file)
@@ -1269,6 +1269,7 @@ void StyleResolver::adjustRenderStyle(RenderStyle& style, const RenderStyle& par
         || style.position() == StickyPosition
         || (style.position() == FixedPosition && documentSettings() && documentSettings()->fixedPositionCreatesStackingContext())
         || style.hasFlowFrom()
+        || style.willChangeCreatesStackingContext()
         ))
         style.setZIndex(0);
 
index 4db6a34..ddbd192 100644 (file)
@@ -113,7 +113,6 @@ class StyleImage;
 class StyleInheritedData;
 class StyleResolver;
 class TransformationMatrix;
-class WillChangeData;
 
 struct ScrollSnapPoints;
 
@@ -1802,6 +1801,14 @@ public:
     WillChangeData* willChange() const { return rareNonInheritedData->m_willChange.get(); }
     void setWillChange(PassRefPtr<WillChangeData>);
 
+    bool willChangeCreatesStackingContext() const
+    {
+        if (!willChange())
+            return false;
+        
+        return willChange()->createsStackingContext();
+    }
+
     const AtomicString& hyphenString() const;
 
     bool inheritedNotEqual(const RenderStyle*) const;
index e631ccf..d3d38fe 100644 (file)
@@ -60,6 +60,55 @@ bool WillChangeData::containsProperty(CSSPropertyID property) const
     return false;
 }
 
+// "If any non-initial value of a property would create a stacking context on the element,
+// specifying that property in will-change must create a stacking context on the element."
+static bool propertyCreatesStackingContext(CSSPropertyID property)
+{
+    switch (property) {
+    case CSSPropertyClipPath:
+    case CSSPropertyWebkitClipPath:
+    case CSSPropertyMask:
+    case CSSPropertyOpacity:
+    case CSSPropertyPosition:
+    case CSSPropertyZIndex:
+    case CSSPropertyWebkitBackfaceVisibility:
+    case CSSPropertyWebkitBoxReflect:
+#if ENABLE(CSS_COMPOSITING)
+    case CSSPropertyMixBlendMode:
+    case CSSPropertyIsolation:
+#endif
+    case CSSPropertyWebkitFilter:
+#if ENABLE(FILTERS_LEVEL_2)
+    case CSSPropertyWebkitBackdropFilter:
+#endif
+    case CSSPropertyWebkitMask:
+    case CSSPropertyWebkitMaskImage:
+    case CSSPropertyWebkitMaskBoxImage:
+    case CSSPropertyPerspective:
+    case CSSPropertyTransform:
+    case CSSPropertyTransformStyle:
+    case CSSPropertyWebkitTransformStyle:
+#if ENABLE(CSS_REGIONS)
+    case CSSPropertyWebkitFlowFrom:
+#endif
+#if ENABLE(ACCELERATED_OVERFLOW_SCROLLING)
+    case CSSPropertyWebkitOverflowScrolling:
+#endif
+        return true;
+    default:
+        return false;
+    }
+}
+
+bool WillChangeData::createsStackingContext() const
+{
+    for (const auto& feature : m_animatableFeatures) {
+        if (feature.feature() == Property && propertyCreatesStackingContext(feature.property()))
+            return true;
+    }
+    return false;
+}
+
 void WillChangeData::addFeature(Feature feature, CSSPropertyID propertyID)
 {
     ASSERT(feature == Property || propertyID == CSSPropertyInvalid);
index 16d9887..81ffeb2 100644 (file)
@@ -53,6 +53,7 @@ public:
     bool containsScrollPosition() const;
     bool containsContents() const;
     bool containsProperty(CSSPropertyID) const;
+    bool createsStackingContext() const;
 
     enum Feature {
         ScrollPosition,