Closed
Bug 964885
Opened 11 years ago
Closed 11 years ago
Track which CSS properties create a stacking context and make will-change on such properties create a stacking context
Categories
(Core :: Layout, enhancement)
Core
Layout
Tracking
()
RESOLVED
FIXED
mozilla30
People
(Reporter: bjacob, Assigned: BenWa)
References
Details
Attachments
(1 file, 3 obsolete files)
12.11 KB,
patch
|
BenWa
:
review+
|
Details | Diff | Splinter Review |
This is branched off bug 940842 comment 79:
(In reply to David Baron [:dbaron] (needinfo? me) (UTC-8) from comment #79)
> Also, it seems like implementing this part of the spec:
>
> ----
> 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.
>
> If a non-initial value of a property would cause rendering differences on
> the element (such as using a different anti-aliasing strategy for text), the
> user agent should use that alternate rendering when the property is
> specified in will-change, to avoid sudden rendering differences when the
> property is eventually changed.
> ----
>
> requires that you track quite a few more CSS properties than you're
> currently tracking. I suspect it means you'll want to track enough
> properties that you'll want to add bits in nsCSSPropList.h to say which
> properties trigger stacking contexts. I'd prefer fixing that in a followup
> patch, but it should happen before the property gets enabled.
Comment 1•11 years ago
|
||
Wouldn't it be better if the CSSWG maintained this list of properties somewhere?
Preferably in a machine readable format so that we could automate a check that
we implement it correctly.
Severity: normal → enhancement
Flags: needinfo?(dbaron)
Assignee | ||
Comment 2•11 years ago
|
||
(In reply to Mats Palmgren (:mats) from comment #1)
> Wouldn't it be better if the CSSWG maintained this list of properties
> somewhere?
> Preferably in a machine readable format so that we could automate a check
> that
> we implement it correctly.
I'd be happy to compile the list based on what we currently do in Layout and submit that to the CSSWG.
Assignee | ||
Updated•11 years ago
|
Assignee: nobody → bgirard
I think the list should be:
z-index, position (for sticky!), opacity, transform, transform-style, perspective, clip-path, filter, mask, mix-blend-mode, plus the aliases -moz-transform, -moz-transform-style, -moz-perspective.
But our implementation looks like it doesn't match specs: we seem to look at backface-visibility (incorrectly) and not look at perspective (which we're supposed to). See isStackingContext in nsIFrame::BuildDisplayListForChild. I suspect we should fix that (separate bug, though).
I'd prefer not to bug the CSS WG about this at this stage.
Flags: needinfo?(dbaron)
(In reply to David Baron [:dbaron] (needinfo? me) (UTC-8) from comment #3)
> But our implementation looks like it doesn't match specs: we seem to look
> at backface-visibility (incorrectly) and not look at perspective (which
> we're supposed to). See isStackingContext in
> nsIFrame::BuildDisplayListForChild. I suspect we should fix that (separate
> bug, though).
I made this bug 968555.
Assignee | ||
Comment 5•11 years ago
|
||
Useful test for stacking context:
http://codepen.io/philipwalton/pen/dfCtb
If div:first-child forces a stacking context the z-index for the red span will be ignored causing it to behind.
Assignee | ||
Comment 6•11 years ago
|
||
Attachment #8371232 -
Flags: review?(dbaron)
Comment on attachment 8371232 [details] [diff] [review]
patch
>diff --git a/layout/style/nsRuleNode.cpp b/layout/style/nsRuleNode.cpp
> case eCSSUnit_List:
> case eCSSUnit_ListDep: {
> display->mWillChange.Clear();
> display->mWillChangeBitField = 0;
>+ display->mWillChangeStackingContext = false;
> for (const nsCSSValueList* item = willChangeValue->GetListValue();
> item; item = item->mNext)
> {
> if (item->mValue.UnitHasStringValue()) {
> nsAutoString buffer;
> item->mValue.GetStringValue(buffer);
> if (buffer.EqualsLiteral("transform")) {
> display->mWillChangeBitField |= NS_STYLE_WILL_CHANGE_TRANSFORM;
> }
> if (buffer.EqualsLiteral("opacity")) {
> display->mWillChangeBitField |= NS_STYLE_WILL_CHANGE_OPACITY;
> }
> if (buffer.EqualsLiteral("scroll-position")) {
> display->mWillChangeBitField |= NS_STYLE_WILL_CHANGE_SCROLL;
> }
>+ if (buffer.EqualsLiteral("z-index") ||
>+ buffer.EqualsLiteral("position") || // position: sticky
>+ buffer.EqualsLiteral("opacity") ||
>+ buffer.EqualsLiteral("transform") ||
>+ buffer.EqualsLiteral("transform-style") ||
>+ buffer.EqualsLiteral("perspective") ||
>+ buffer.EqualsLiteral("clip-path") ||
>+ buffer.EqualsLiteral("filter") ||
>+ buffer.EqualsLiteral("mask") ||
>+ buffer.EqualsLiteral("mix-blend-mode") ||
>+ buffer.EqualsLiteral("-moz-transform") ||
>+ buffer.EqualsLiteral("-moz-transform-style") ||
>+ buffer.EqualsLiteral("-moz-perspective")) {
>+ display->mWillChangeStackingContext = true;
>+ }
> display->mWillChange.AppendElement(buffer);
Instead of hard-coding a list here, please add a bit to nsCSSProps.h (CSS_PROPERTY_CREATES_STACKING_CONTEXT, 1<<22 unless somebody beats you to it), add that bit to the above list of properties (you shouldn't need to touch the aliases), and use nsCSSProps::LookupProperty and nsCSSProps:PropHasFlags
> case eCSSUnit_Inherit:
> display->mWillChange = parentDisplay->mWillChange;
You need to copy this in the eCSSUnit_Inherit case, and reset it in the Initial/Unset/Auto case. (But see comment below about using the bitfield.)
>diff --git a/layout/style/nsStyleStruct.cpp b/layout/style/nsStyleStruct.cpp
>@@ -2462,17 +2464,18 @@ nsChangeHint nsStyleDisplay::CalcDiffere
> if (mChildPerspective != aOther.mChildPerspective ||
> mTransformStyle != aOther.mTransformStyle)
> NS_UpdateHint(hint, kUpdateOverflowAndRepaintHint);
>
> if (mBackfaceVisibility != aOther.mBackfaceVisibility)
> NS_UpdateHint(hint, nsChangeHint_RepaintFrame);
> }
>
>- if (mWillChangeBitField != aOther.mWillChangeBitField) {
>+ if (mWillChangeBitField != aOther.mWillChangeBitField ||
>+ mWillChangeStackingContext != aOther.mWillChangeStackingContext) {
> NS_UpdateHint(hint, nsChangeHint_ReconstructFrame);
> }
I think this is overkill in both cases (the existing BitField case, and your new case). I believe RepaintFrame should be sufficient for mWillChangeStackingContext.
(The existing case is a little more complicated, but we should probably have a bug on file on improving it. The whole thing about this being a property for performance optimization doesn't work out so well if it performs badly.)
>diff --git a/layout/style/nsStyleStruct.h b/layout/style/nsStyleStruct.h
> uint8_t mWillChangeBitField; // [reset] see nsStyleConsts.h. Stores a bitfield
> // representation of the property that
> // are frequently queried. This should match
> // mWillChange
>+ bool mWillChangeStackingContext; // Do any of the will-change property in
>+ // the list require a stacking context
Please:
* add [reset] to the start of the comment
* "the will-change property in the list" -> "the properties in the will-change list"
However... why not just use a bit in the bitfield instead of adding a whole separate boolean (which will probably take up 32/64 bits!). That also simplifies the above comments about the Inherit and Initial cases.
Sorry for the delay getting to this.
Attachment #8371232 -
Flags: review?(dbaron) → review-
Assignee | ||
Comment 8•11 years ago
|
||
(In reply to David Baron [:dbaron] (needinfo? me) (UTC-8) from comment #7)
> Instead of hard-coding a list here, please add a bit to nsCSSProps.h
> (CSS_PROPERTY_CREATES_STACKING_CONTEXT, 1<<22 unless somebody beats you to
> it), add that bit to the above list of properties (you shouldn't need to
> touch the aliases), and use nsCSSProps::LookupProperty and
> nsCSSProps:PropHasFlags
Thanks, I was hoping you would suggest something better in the review!
> (The existing case is a little more complicated, but we should probably have
> a bug on file on improving it. The whole thing about this being a property
> for performance optimization doesn't work out so well if it performs badly.)
Ok, I'll get that file. I haven't spent much time trying to understand that hoping this would be easy for you to catch. With some guidance I can look at the follow up.
> boolean (which will probably take up 32/64 bits!).
8 bits size/align on all the ABIs I know, but good point.
Assignee | ||
Comment 9•11 years ago
|
||
Attachment #8371232 -
Attachment is obsolete: true
Attachment #8377920 -
Flags: review?(dbaron)
Assignee | ||
Comment 10•11 years ago
|
||
Comment on attachment 8377920 [details] [diff] [review]
patch
Review of attachment 8377920 [details] [diff] [review]:
-----------------------------------------------------------------
::: layout/style/nsStyleStruct.cpp
@@ +2467,5 @@
> NS_UpdateHint(hint, nsChangeHint_RepaintFrame);
> }
>
> if (mWillChangeBitField != aOther.mWillChangeBitField) {
> + if ((mWillChangeBitField & ~(uint32_t)NS_WILL_CHANGE_STACKING_CONTEXT) ==
Not a fan of how this turned out. bjacob thinks we can make this simpler with templates. There's a way to write this with XOR but I think it's a bit more complicated. Let me know if you're happy.
Assignee | ||
Comment 11•11 years ago
|
||
This was missing a replacement I had locally.
Attachment #8377920 -
Attachment is obsolete: true
Attachment #8377920 -
Flags: review?(dbaron)
Attachment #8378461 -
Flags: review?(dbaron)
Assignee | ||
Comment 12•11 years ago
|
||
Comment on attachment 8378461 [details] [diff] [review]
patch
Could you add the comment about the position annotation being for sticky to
nsCSSPropList.h?
>+ if (nsCSSProps::PropHasFlags(prop,
>+ CSS_PROPERTY_CREATES_STACKING_CONTEXT)) {
(1) you need to check prop != eCSSProperty_UNKNOWN && nsCSSProps::PropHasFlags
(2) please line up the second param with the first, or if that goes over 80,
then 2 spaces in from the "nsCSSProps" (not 2 spaces in from the "if")
>+ // bitfield representation of the property that
property that -> properties that
>+ if ((mWillChangeBitField & ~(uint32_t)NS_STYLE_WILL_CHANGE_STACKING_CONTEXT) ==
>+ (aOther.mWillChangeBitField & ~(uint32_t)NS_STYLE_WILL_CHANGE_STACKING_CONTEXT)) {
>+ NS_UpdateHint(hint, nsChangeHint_RepaintFrame);
>+ } else {
>+ // Bug 974125 - Don't reconstruct the frame
>+ NS_UpdateHint(hint, nsChangeHint_ReconstructFrame);
>+ }
Please write the fixme comment as "FIXME (bug 974125): Don't ...".
Also, I think it would be a lot simpler and clearer to do:
uint8_t willChangeBitsChanged =
mWillChangeBitField ^ aOther.mWillChangeBitField;
if (willChangeBitsChanged & NS_STYLE_WILL_CHANGE_STACKING_CONTEXT) {
NS_UpdateHint(hint, nsChangeHint_RepaintFrame);
}
if (willChangeBitsChanged & ~uint8_t(NS_STYLE_WILL_CHANGE_STACKING_CONTEXT)) {
// FIXME (Bug 974125): Don't reconstruct the frame
NS_UpdateHint(hint, nsChangeHint_ReconstructFrame);
}
r=dbaron with that
Attachment #8378461 -
Flags: review?(dbaron) → review+
Assignee | ||
Comment 14•11 years ago
|
||
Waiting on tryresults
Attachment #8378461 -
Attachment is obsolete: true
Attachment #8378525 -
Flags: review+
Assignee | ||
Comment 15•11 years ago
|
||
Comment 16•11 years ago
|
||
Status: NEW → RESOLVED
Closed: 11 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla30
Depends on: 1195142
You need to log in
before you can comment on or make changes to this bug.
Description
•