Closed Bug 1442190 Opened 7 years ago Closed 7 years ago

Flatten inactive nsDisplayOpacity display items

Categories

(Core :: Web Painting, enhancement, P2)

enhancement

Tracking

()

RESOLVED FIXED
mozilla61
Tracking Status
firefox61 --- fixed

People

(Reporter: mikokm, Assigned: mikokm)

References

(Blocks 1 open bug)

Details

Attachments

(6 files, 3 obsolete files)

This bug tracks the work of implementing flattening, as described in bug 1439292, for nsDisplayOpacity items.
Attached patch wip.diff (obsolete) — Splinter Review
Current work in progress.
Priority: -- → P2
Attachment #8955080 - Attachment is patch: true
Attachment #8955080 - Attachment mime type: text/x-patch → text/plain
Attached patch wip-v2.diff (obsolete) — Splinter Review
https://treeherder.mozilla.org/#/jobs?repo=try&revision=de7d856e3e4b36f2267e5a395fb1c3fdeef42191 There are still a couple of problems with clipping and invalidation.
Attachment #8955080 - Attachment is obsolete: true
Attached patch flatten-opacity.patch (obsolete) — Splinter Review
Attachment #8957207 - Attachment is obsolete: true
Attachment #8960823 - Attachment is obsolete: true
These patches enable flattening of inactive nsDisplayOpacity items in FrameLayerBuilder. This is done by tracking when the opacity items are flattened, and emitting PUSH_OPACITY and POP_OPACITY markers around the children. Brief summary: -------------- Part 1: In order to properly invalidate the area painted by nsDisplayOpacity, nsDisplayOpacityGeometry is added to track opacity value changes. Part 2: Adds unimplemented virtual methods StartNested(nsDisplayItem* aItem) and EndNested(nsDisplayItem* aItem) to FlattenedDisplayItemIterator. These are called when a display item is flattened. Part 3: Adds functionality to distinguish whether nsDisplayOpacity has applied opacity to the children. This is needed to avoid applying opacity twice, and to support (old) flattening with WebRender. An alternative way to implement this would have been to replace return value for all display items that implement ShouldFlatten(). This approach might be nicer solution in the future if/when other effects are flattened. Part 4: Adds FLBDisplayItemIterator that implements StartNested() and EndNested() functions and uses them to emit PUSH_OPACITY and POP_OPACITY markers when entering/leaving nested list. ShouldFlattenNextItem() is overridden to check whether nsDisplayOpacity will use active layers, in which case we do not flatten it. Part 5: Replaces FlattenedDisplayItemIterator with FLBDisplayItemIterator in ContainerState::ProcessDisplayItems(). The display items are tagged with either ITEM, PUSH_OPACITY, or POP_OPACITY markers, that are stored in AssignedDisplayItem struct along with the item. Most of the changes are to ensure that subpixel aa, invalidation, and visibility calculations work correctly with the markers. The actual use of the opacity markers happens in FrameLayerBuilder::PaintItems(). The complexity there comes mainly from having to track multiple nested clips for and within temporary surfaces. Part 6: Three reftests had to be fuzzed. - 654950-1-ref.html: There is an existing comment about blending. Off by one in one color component sounds reasonable. - grid-abspos-items-002.html: Looks like it could be caused by missing layer clip[1]. - anonymous-block.html: Subpixel AA for the text has a slightly different intensity. [1]: https://searchfox.org/mozilla-central/rev/b29daa46443b30612415c35be0a3c9c13b9dc5f6/layout/generic/nsTextFrame.cpp#5139
Attachment #8961032 - Flags: review?(matt.woodrow) → review+
Comment on attachment 8961033 [details] Bug 1442190 - Part 2: Virtualize FlattenedDisplayItemIterator and move it to a more appropriate place https://reviewboard.mozilla.org/r/229766/#review235682 ::: layout/painting/nsDisplayList.h:3212 (Diff revision 1) > +class FlattenedDisplayItemIterator > +{ > +public: > + FlattenedDisplayItemIterator(nsDisplayListBuilder* aBuilder, > + nsDisplayList* aList, > + const bool aResolveFlattening) Make this default to true so that the existing callers don't need to care about it.
Attachment #8961033 - Flags: review?(matt.woodrow) → review+
Comment on attachment 8961033 [details] Bug 1442190 - Part 2: Virtualize FlattenedDisplayItemIterator and move it to a more appropriate place https://reviewboard.mozilla.org/r/229766/#review235684 I don't think we need to make things virtual here. We don't have any code that refers to a FLBDisplayItemIterator via a FlattenedDisplayItemIterator, so we shouldn't need virtual function to resolve to the derived class. Instead we can just make FLBDisplayItemIterator use protected inheritance (and add an implementation forwarding PeekNext), and then everything will be resolved at compile-time. r=me with the 'virtual' additions removed.
Comment on attachment 8961034 [details] Bug 1442190 - Part 3: Add functionality to know whether nsDisplayOpacity::ShouldFlattenAway() applied opacity to children https://reviewboard.mozilla.org/r/229768/#review235686 ::: layout/painting/nsDisplayList.h:5224 (Diff revision 1) > nsDisplayOpacity(nsDisplayListBuilder* aBuilder, > const nsDisplayOpacity& aOther) > : nsDisplayWrapList(aBuilder, aOther) > , mOpacity(aOther.mOpacity) > , mForEventsAndPluginsOnly(aOther.mForEventsAndPluginsOnly) > + , mOpacityAppliedToChildren(aOther.mOpacityAppliedToChildren) We block flattening if we might need to merge, so aOther.mOpacityAppliedToChildren must be false. We should just set our version to false, and assert that the aOther's is false too. ::: layout/painting/nsDisplayList.cpp:6709 (Diff revision 1) > } > > +bool > +nsDisplayOpacity::ShouldFlattenAway(nsDisplayListBuilder* aBuilder) > +{ > + if (mOpacityAppliedToChildren) { If this ever succeeds, then it means we've called ShouldFlattenAway twice, which is probably a bad thing (especially since we're only caching the result if it was true). Does that happen? Can we instead just assert that it doesn't?
Attachment #8961034 - Flags: review?(matt.woodrow) → review+
Comment on attachment 8961033 [details] Bug 1442190 - Part 2: Virtualize FlattenedDisplayItemIterator and move it to a more appropriate place https://reviewboard.mozilla.org/r/229766/#review235684 Sorry, this wasn't very clear. The public interface doesn't need to be virtual, ShouldFlattenNextItem/StartNested/EndNested obviously do.
Comment on attachment 8961035 [details] Bug 1442190 - Part 4: Add FLBDisplayItemIterator https://reviewboard.mozilla.org/r/229770/#review235692 ::: layout/painting/FrameLayerBuilder.cpp:181 (Diff revision 1) > + void StartNested(nsDisplayItem* aItem) override > + { > + if (aItem->GetType() == DisplayItemType::TYPE_OPACITY) { > + nsDisplayOpacity* opacity = static_cast<nsDisplayOpacity*> (aItem); > + > + if (opacity->OpacityAppliedToChildren()) { We could probably combine these two checks into a single call (a virtual on nsDisplayItem), something like bool NeedsMarkerForFlattening(DisplayItemEntryType* aOutMarkerType). Sets you up better for supporting types other than opacity in the future. ::: layout/painting/FrameLayerBuilder.cpp:1597 (Diff revision 1) > + return false; > + } > + > + const bool shouldFlatten = mNext->ShouldFlattenAway(mBuilder); > + > + if (!shouldFlatten) { Can just do if (!mNext->ShouldFlattenAway()) { return false;} We use shouldFlatten again at the end, but it's guaranteed to be true.
Attachment #8961035 - Flags: review?(matt.woodrow) → review+
Attachment #8961037 - Flags: review?(matt.woodrow) → review+
Comment on attachment 8961036 [details] Bug 1442190 - Part 5: Use FLBDisplayItemIterator and flatten inactive nsDisplayOpacity in more cases https://reviewboard.mozilla.org/r/229772/#review235702 ::: layout/painting/FrameLayerBuilder.cpp:1743 (Diff revision 1) > bool mDisabledAlpha; > > + /** > + * True if the painted layer has text items. > + */ > + bool mHasTextItems; I think this should be a property of the AssignedDisplayItem(mType == PUSH_OPACITY). We don't want to copy the background into our temporaries if text exists outside of the opacity. I think you'll need to keep a stack of currently applied PUSH_OPACITYs (and replace opacityNesting with opacityStack.Length()), which contain a pointer to the AssignedDisplayItem entry we created for that marker. When we encounter text, set mHasTextItems = true on all entries in the opacityStack. It's possible that you could share the existing stack in FLBDisplayItemIterator, but it might be hard to find an understandable abstraction around that.
Comment on attachment 8961036 [details] Bug 1442190 - Part 5: Use FLBDisplayItemIterator and flatten inactive nsDisplayOpacity in more cases https://reviewboard.mozilla.org/r/229772/#review235702 > I think this should be a property of the AssignedDisplayItem(mType == PUSH_OPACITY). > > We don't want to copy the background into our temporaries if text exists outside of the opacity. > > I think you'll need to keep a stack of currently applied PUSH_OPACITYs (and replace opacityNesting with opacityStack.Length()), which contain a pointer to the AssignedDisplayItem entry we created for that marker. > > When we encounter text, set mHasTextItems = true on all entries in the opacityStack. > > It's possible that you could share the existing stack in FLBDisplayItemIterator, but it might be hard to find an understandable abstraction around that. This is now fixed. I solved it by using an array containing indices to mAssignedDisplayItems and changing PUSH_OPACITY type to PUSH_OPACITY_WITH_BG when items needing subpixel AA are encountered.
Comment on attachment 8961036 [details] Bug 1442190 - Part 5: Use FLBDisplayItemIterator and flatten inactive nsDisplayOpacity in more cases https://reviewboard.mozilla.org/r/229772/#review240790 ::: layout/painting/FrameLayerBuilder.cpp:3704 (Diff revision 3) > > bool isFirstVisibleItem = mVisibleRegion.IsEmpty(); > > - Maybe<nscolor> uniformColor = aItem->IsUniform(aState->mBuilder); > + Maybe<nscolor> uniformColor; > + if (!aHasOpacity) { > + uniformColor = aItem->IsUniform(aState->mBuilder); Probably a TODO, but we could still be a uniform color with opacity couldn't we? ::: layout/painting/FrameLayerBuilder.cpp:4854 (Diff revision 3) > + > + if (marker == DisplayItemEntryType::POP_OPACITY) { > + MOZ_ASSERT(selectedPLD && opacityNesting > 0); > + opacityNesting--; > + > + if (opacityNesting == 0) { Seems like we could remove opacityNesting and just use selectedPLD->mOpacityIndices.Length(). ::: layout/painting/FrameLayerBuilder.cpp:6154 (Diff revision 3) > } > + > + if (cdi->mType == DisplayItemEntryType::POP_OPACITY || > + (cdi->mType == DisplayItemEntryType::ITEM && cdi->mHasOpacity)) { > + // The visibility calculations are skipped when the item is an effect end > + // marker, or when the display item is within a flattened opacity group. Maybe mention that the reason we skip items within a flattened group is that we should have already called RecomputeVisibility on the group display item, which includes recursing into this child. ::: layout/painting/FrameLayerBuilder.cpp:6216 (Diff revision 3) > + > + nsDisplayOpacity* opacityItem = static_cast<nsDisplayOpacity*>(aItem.mItem); > + const float opacity = opacityItem->GetOpacity(); > + > + if (aItem.mType == DisplayItemEntryType::PUSH_OPACITY_WITH_BG) { > + aContext->PushGroupAndCopyBackground(gfxContentType::COLOR_ALPHA, opacity); I believe this is only valid if the destination is going to be opaque (either a gfxContentType::COLOR surface, or has opaque pixels drawn to it). We don't compute the latter, so I think you just want to check the former in the if condition. The condition might also need DrawTarget::SetPermitSubpixelAA(false), since I'm pretty sure PaintedLayerData::Accumulate isn't calling nsDisplayItem::DisableComponentAlpha() for us in this case.
Attachment #8961036 - Flags: review?(matt.woodrow) → review+
Comment on attachment 8961036 [details] Bug 1442190 - Part 5: Use FLBDisplayItemIterator and flatten inactive nsDisplayOpacity in more cases https://reviewboard.mozilla.org/r/229772/#review241032 ::: layout/painting/FrameLayerBuilder.cpp:6154 (Diff revision 3) > } > + > + if (cdi->mType == DisplayItemEntryType::POP_OPACITY || > + (cdi->mType == DisplayItemEntryType::ITEM && cdi->mHasOpacity)) { > + // The visibility calculations are skipped when the item is an effect end > + // marker, or when the display item is within a flattened opacity group. Done.
We're sorry, Autoland could not rebase your commits for you automatically. Please manually rebase your commits and try again. hg error in cmd: hg rebase -s da0c1b74a1f0a1918b8b84bdf66ce8a0b95410a7 -d 964dbe5e2afe: rebasing 457209:da0c1b74a1f0 "Bug 1442190 - Part 1: Add nsDisplayOpacityGeometry r=mattwoodrow" merging layout/painting/nsDisplayList.cpp merging layout/painting/nsDisplayList.h rebasing 457210:59b2e143ab28 "Bug 1442190 - Part 2: Virtualize FlattenedDisplayItemIterator and move it to a more appropriate place r=mattwoodrow" merging layout/painting/nsDisplayList.h rebasing 457211:7ba6014ca3b9 "Bug 1442190 - Part 3: Add functionality to know whether nsDisplayOpacity::ShouldFlattenAway() applied opacity to children r=mattwoodrow" merging layout/painting/nsDisplayList.cpp merging layout/painting/nsDisplayList.h rebasing 457212:03cf17f1a860 "Bug 1442190 - Part 4: Add FLBDisplayItemIterator r=mattwoodrow" merging layout/painting/FrameLayerBuilder.cpp rebasing 457213:c3b07cdd589f "Bug 1442190 - Part 5: Use FLBDisplayItemIterator and flatten inactive nsDisplayOpacity in more cases r=mattwoodrow" merging layout/painting/FrameLayerBuilder.cpp merging layout/painting/nsDisplayList.cpp rebasing 457214:56d8c5259cb6 "Bug 1442190 - Part 6: Make three reftests fuzzy r=mattwoodrow" (tip) merging layout/reftests/bugs/reftest.list merging layout/reftests/css-grid/reftest.list merging layout/reftests/text-overflow/reftest.list warning: conflicts while merging layout/reftests/text-overflow/reftest.list! (edit, then use 'hg resolve --mark') unresolved conflicts (see hg resolve, then hg rebase --continue)
Pushed by mikokm@gmail.com: https://hg.mozilla.org/integration/autoland/rev/7f82627c75fa Part 1: Add nsDisplayOpacityGeometry r=mattwoodrow https://hg.mozilla.org/integration/autoland/rev/8018f83c161b Part 2: Virtualize FlattenedDisplayItemIterator and move it to a more appropriate place r=mattwoodrow https://hg.mozilla.org/integration/autoland/rev/9503cb9d5fc1 Part 3: Add functionality to know whether nsDisplayOpacity::ShouldFlattenAway() applied opacity to children r=mattwoodrow https://hg.mozilla.org/integration/autoland/rev/c992deef1ec5 Part 4: Add FLBDisplayItemIterator r=mattwoodrow https://hg.mozilla.org/integration/autoland/rev/1ca2a0266f20 Part 5: Use FLBDisplayItemIterator and flatten inactive nsDisplayOpacity in more cases r=mattwoodrow https://hg.mozilla.org/integration/autoland/rev/db65cdb10a34 Part 6: Make three reftests fuzzy r=mattwoodrow
(In reply to Andreea Pavel [:apavel] from comment #40) > Backed out for failing reftest text-overflow/anonymous-block.html, at least > on OS X > > Push that caused the failures: > https://treeherder.mozilla.org/#/ > jobs?repo=autoland&revision=db65cdb10a345cabb8e8c714285edfd0dff0cd1a > > Failure log: > https://treeherder.mozilla.org/logviewer. > html#?job_id=173087505&repo=autoland&lineNumber=5835 > > Backout: > https://hg.mozilla.org/integration/autoland/rev/ > 3cd75c11b4ff40527bf347fef1a69eec1ad5f2c4 This reftest was supposed to be marked fuzzy, but a chunk was lost during rebasing.
Flags: needinfo?(mikokm)
Pushed by mikokm@gmail.com: https://hg.mozilla.org/integration/autoland/rev/f8c99ac6bf0d Part 1: Add nsDisplayOpacityGeometry r=mattwoodrow https://hg.mozilla.org/integration/autoland/rev/7a1185d616dc Part 2: Virtualize FlattenedDisplayItemIterator and move it to a more appropriate place r=mattwoodrow https://hg.mozilla.org/integration/autoland/rev/cebcdd61afcb Part 3: Add functionality to know whether nsDisplayOpacity::ShouldFlattenAway() applied opacity to children r=mattwoodrow https://hg.mozilla.org/integration/autoland/rev/ce317da6a8fc Part 4: Add FLBDisplayItemIterator r=mattwoodrow https://hg.mozilla.org/integration/autoland/rev/e406251cf5ea Part 5: Use FLBDisplayItemIterator and flatten inactive nsDisplayOpacity in more cases r=mattwoodrow https://hg.mozilla.org/integration/autoland/rev/e8dc919d0f42 Part 6: Make three reftests fuzzy r=mattwoodrow
(In reply to Noemi Erli[:noemi_erli] from comment #44) > Backed out 6 changesets (bug 1442190) for reftest failures on > /anonymous-block.html on a CLOSED TREE > > Push with failures: > https://treeherder.mozilla.org/#/ > jobs?repo=autoland&revision=e8dc919d0f426ae2f4a0f4d7f87115a3beb08294&filter- > resultStatus=testfailed&filter-resultStatus=busted&filter- > resultStatus=exception&filter-resultStatus=retry&filter- > resultStatus=usercancel&filter-resultStatus=runnable&filter- > resultStatus=pending&filter-resultStatus=running&selectedJob=173131388 > > Failure log: > https://treeherder.mozilla.org/logviewer. > html#?job_id=173131388&repo=autoland&lineNumber=1824 > > Backout: > https://hg.mozilla.org/integration/autoland/rev/ > 4fd59fe7f0f847701f154e03e463757baa021837 The cause for this failure is a slight brightness difference in subpixel aa text, caused by flattening. It seems that Windows 10 and Windows 7 need a different fuzzing for this. I have fixed this, and I am pushing the changes again, after the (this time exhaustive) try run is finished.
Flags: needinfo?(mikokm)
We're sorry, Autoland could not rebase your commits for you automatically. Please manually rebase your commits and try again. hg error in cmd: hg rebase -s ccc6a2f531541b0d6dfce79bf0d1685cb9298f01 -d 93c851a45ec7: rebasing 457666:ccc6a2f53154 "Bug 1442190 - Part 1: Add nsDisplayOpacityGeometry r=mattwoodrow" merging layout/painting/nsDisplayList.cpp merging layout/painting/nsDisplayList.h merging layout/painting/nsDisplayListInvalidation.h rebasing 457667:aed465eaaa5d "Bug 1442190 - Part 2: Virtualize FlattenedDisplayItemIterator and move it to a more appropriate place r=mattwoodrow" merging layout/painting/nsDisplayList.h rebasing 457668:c8da49ae5ac2 "Bug 1442190 - Part 3: Add functionality to know whether nsDisplayOpacity::ShouldFlattenAway() applied opacity to children r=mattwoodrow" merging layout/painting/nsDisplayList.cpp merging layout/painting/nsDisplayList.h rebasing 457669:830b45b588ec "Bug 1442190 - Part 4: Add FLBDisplayItemIterator r=mattwoodrow" merging layout/painting/FrameLayerBuilder.cpp merging layout/painting/FrameLayerBuilder.h rebasing 457670:558bc2277602 "Bug 1442190 - Part 5: Use FLBDisplayItemIterator and flatten inactive nsDisplayOpacity in more cases r=mattwoodrow" merging layout/painting/FrameLayerBuilder.cpp merging layout/painting/FrameLayerBuilder.h merging layout/painting/nsDisplayList.cpp warning: conflicts while merging layout/painting/FrameLayerBuilder.cpp! (edit, then use 'hg resolve --mark') unresolved conflicts (see hg resolve, then hg rebase --continue)
Pushed by mikokm@gmail.com: https://hg.mozilla.org/integration/autoland/rev/df7030abb8e1 Part 1: Add nsDisplayOpacityGeometry r=mattwoodrow https://hg.mozilla.org/integration/autoland/rev/f4a9c1f73c1d Part 2: Virtualize FlattenedDisplayItemIterator and move it to a more appropriate place r=mattwoodrow https://hg.mozilla.org/integration/autoland/rev/faf8093a7fbc Part 3: Add functionality to know whether nsDisplayOpacity::ShouldFlattenAway() applied opacity to children r=mattwoodrow https://hg.mozilla.org/integration/autoland/rev/3bb3af9020e1 Part 4: Add FLBDisplayItemIterator r=mattwoodrow https://hg.mozilla.org/integration/autoland/rev/7c3ec4cce489 Part 5: Use FLBDisplayItemIterator and flatten inactive nsDisplayOpacity in more cases r=mattwoodrow https://hg.mozilla.org/integration/autoland/rev/665843c6cfd1 Part 6: Make three reftests fuzzy r=mattwoodrow
Depends on: 1453944
Depends on: 1454653
Depends on: 1455908
Depends on: 1455944
Depends on: 1454105
Depends on: 1461177
No longer depends on: 1461177
Depends on: 1471181
Depends on: 1472465
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: