Closed Bug 1617427 Opened 4 years ago Closed 4 years ago

Text in an overflow-x: auto container fails to render while scrolling after opening dev tools

Categories

(Core :: Panning and Zooming, defect, P2)

72 Branch
Desktop
All
defect

Tracking

()

VERIFIED FIXED
mozilla76
Tracking Status
firefox-esr68 --- wontfix
firefox73 --- wontfix
firefox74 --- wontfix
firefox75 --- wontfix
firefox76 --- verified
firefox77 --- verified

People

(Reporter: hasan, Assigned: kats)

References

Details

Attachments

(9 files)

1.76 KB, text/html
Details
47 bytes, text/x-phabricator-request
Details | Review
47 bytes, text/x-phabricator-request
Details | Review
47 bytes, text/x-phabricator-request
Details | Review
47 bytes, text/x-phabricator-request
Details | Review
47 bytes, text/x-phabricator-request
Details | Review
47 bytes, text/x-phabricator-request
Details | Review
47 bytes, text/x-phabricator-request
Details | Review
47 bytes, text/x-phabricator-request
Details | Review
Attached file test.html

User Agent: Mozilla/5.0 (X11; Fedora; Linux x86_64; rv:72.0) Gecko/20100101 Firefox/72.0

Steps to reproduce:

  1. Open test.html
  2. Open dev tools (hitting f12)
  3. Scrolling page

Actual results:

Region that I scrolled to was white until I clicked.

This behaviour goes away once you get rid of the overflow-x: auto on the pre element.

Expected results:

The scrolled to region should have the appropriately rendered text.

I can reproduce this issue on Windows 10 on the latest versions of the 4 main channels, however, this issue is somewhat partially reproduced on Mac OS. The content is rendered in Mac OS, just a little delayed.

Status: UNCONFIRMED → NEW
Has STR: --- → yes
Component: Untriaged → Layout: Text and Fonts
Ever confirmed: true
OS: Unspecified → All
Product: Firefox → Core
Hardware: Unspecified → Desktop

To be clear, the devtools need to be docked to the bottom for the bug to repro. I have my devtools in a different window and I couldn't initially repro.

This smells like APZ rather than layout. I know that devtools has some interactions with APZ... Botond, any ideas?

Flags: needinfo?(botond)
Component: Layout: Text and Fonts → Panning and Zooming

What seems to be happening here is:

  • Devtools disables APZ for the subframe (via this mechanism). APZ is still enabled for the root frame.
  • As a result, we don't paint a displayport for the subframe, we only paint its viewport.
  • Additionally, we clip the subframe's viewport to the viewport of the root frame. (This is to avoid rendering too much in case where a subframe has a huge viewport.)
  • When you then scroll the root frame, it scrolls with APZ and paint skipping, but it brings into view parts of the subframe's viewport which haven't been rendered. Those parts are then never painted until something like a click event triggers a repaint.
Flags: needinfo?(botond)

(In reply to Botond Ballo [:botond] from comment #3)

  • Additionally, we clip the subframe's viewport to the viewport of the root frame. (This is to avoid rendering too much in case where a subframe has a huge viewport.)

I think conceptually the problem is here: we should be clipping the subframe's viewport to the displayport of the root frame. Then, the root frame can scroll with APZ and paint skipping just fine within the root frame's displayport. If we scroll the root frame far enough to move its displayport, we'll paint a new displayport including new regions of the subframe's viewport.

P2 as this is a perma-checkerboarding issue (albeit one we've been shipping for a while).

Priority: -- → P2

I can take a look at this.

Assignee: nobody → kats

(In reply to Botond Ballo [:botond] from comment #3)

What seems to be happening here is:

  • Devtools disables APZ for the subframe (via this mechanism). APZ is still enabled for the root frame.
  • As a result, we don't paint a displayport for the subframe, we only paint its viewport.
  • Additionally, we clip the subframe's viewport to the viewport of the root frame. (This is to avoid rendering too much in case where a subframe has a huge viewport.)
  • When you then scroll the root frame, it scrolls with APZ and paint skipping, but it brings into view parts of the subframe's viewport which haven't been rendered. Those parts are then never painted until something like a click event triggers a repaint.

This is mostly correct, except that strictly speaking, we do still have a displayport for the subframe. It's just that it uses zero margins to inflate (here) and so gets sized to the "display port base" size, rounded up to the nearest tile. The "display port base" size is computed in the block of code below this comment, and was the subject of much fiddling back in the day (see bug 1327095 and friends).

But yes, fundamentally the problem does seem to be that it uses the root composition bounds (i.e. the viewport of the root frame) as one of the clipping factors for the display port base, and increasing that to use the root displayport instead will likely fix the problem. Doing that might be nontrivial but I can try.

Braindump of current state:

  • patches are at https://treeherder.mozilla.org/#/jobs?repo=try&group_state=expanded&revision=7b25952b97afc2a34cc31701ffb185222727be72 and seem to work fine. I manually tested a few different scenarios including the case where the subframe has a CSS scale transform and things look good.
  • trying to write a mochitest to exercise this bug is hard. My plan was to set up the situation that reproduces the checkerboard and then to somehow test for whether or not checkerboarding was happening
  • setting up the checkerboard situation is working now, I had to add a DWU method to disable apz on an element but it wasn't too bad
  • testing for checkerboarding is a little harder, because we need to compute the user-visible part of a scrollframe which involves walking up the APZ tree and doing intersections
  • while doing this I discovered that the IsCurrentlyCheckerboarding function is not hooked up to anything

I finally got the mochitest working and hammered out all the intermittents I could find. Ran it with --verify without the patch to ensure it failed consistently and then ran it with --verify with the patch to validate the fix.

Try push is at https://treeherder.mozilla.org/#/jobs?repo=try&revision=552500bc43d22d23a8ed7fa5063228c871afe28e

Assuming that's good, I'll rebase to current master, do any clang-formatting/static analysis fixes, and put it up for review.

Hm, test doesn't work on android because I used wheel events which aren't supported there. I can probably adjust the test to not use wheel events, will give that a shot first.

If we can get the root frame's displayport, then we should use that
rect instead of the root composition bounds when clipping the scrollframe's
displayport. That way if APZ is disabled on the scrollframe, but the root
frame scrolls to bring a part of it into view, it will be fully painted and
not perma-checkerboard-y.

Note that this patch is the main fix, but leaves a bunch of comments/variables
with bad names; the next patch cleans that up.

Depends on D66420

Slight functional changes:

  • the checkerboard event call site will now include mTestAsyncScrollOffset
    when calculating the visible rect, which should impact overall behaviour if
    there's a test that cares about checkerboard events (there currently isn't).
  • the IsCurrentlyCheckerboarding call site will use the compositing effective
    scroll offset instead of the raw metrics scroll offset. This function is
    not called from anywhere so it doesn't matter, but it makes sense to align
    it with the other uses and I'll be using it in future patches.

Depends on D66425

This improves the implementation of IsCurrentlyCheckerboarding (which is not
invoked from anywhere prior to this patch) so that it takes into account the
recursive clipping applied by ancestor layers' composition bounds. In other
words, the visible rect for a layer may be additionally clipped because
ancestor scrollframes have scrolled, and this patch accounts for that.

It also records the currently-checkerboarding state into the APZTestData
at the time that the compositor APZTestData instance is fetched.

Depends on D66426

(In reply to Kartikaya Gupta (email:kats@mozilla.com) from comment #7)

But yes, fundamentally the problem does seem to be that it uses the root composition bounds (i.e. the viewport of the root frame) as one of the clipping factors for the display port base, and increasing that to use the root displayport instead will likely fix the problem. Doing that might be nontrivial but I can try.

So this means that we could get a "multiply effect", where the displayport base of a non-root scroll frame is set based on the displayport of the root, and then the displayport of the non-root element is expanded from the displayport base to it's displayport. The multiplication though is limited to that, we can't get a chain of displayport bases that are in turn based on an ancestor displayport, since we always look at the root displayport. So there is still some finite upper bound, which is the important part. We are increasing the upper bound though.

(In reply to Timothy Nikkel (:tnikkel) from comment #19)

So this means that we could get a "multiply effect", where the displayport base of a non-root scroll frame is set based on the displayport of the root, and then the displayport of the non-root element is expanded from the displayport base to it's displayport. The multiplication though is limited to that, we can't get a chain of displayport bases that are in turn based on an ancestor displayport, since we always look at the root displayport. So there is still some finite upper bound, which is the important part. We are increasing the upper bound though.

Yes, agreed.

Pushed by kgupta@mozilla.com:
https://hg.mozilla.org/integration/autoland/rev/296aad2e1950
Refactor to extract helper method; no functional changes. r=tnikkel
https://hg.mozilla.org/integration/autoland/rev/275f9a696ae1
Prefer using the root frame's displayport to the root composition bounds. r=tnikkel
https://hg.mozilla.org/integration/autoland/rev/2e6aefd7a093
Rename things and fix up comments. r=tnikkel
https://hg.mozilla.org/integration/autoland/rev/c1c55cb6cf31
Add a DOMWindowUtils API to disable APZ on a particular element. r=tnikkel
https://hg.mozilla.org/integration/autoland/rev/ba8c8fe461d5
Miscellaenous documentation fixes. r=botond
https://hg.mozilla.org/integration/autoland/rev/6af812a825de
Extract helper method to normalize visible rect computation. r=botond
https://hg.mozilla.org/integration/autoland/rev/35d9d70da6c9
Resurrect IsCurrentlyCheckerboarding and make it more correct. r=botond
https://hg.mozilla.org/integration/autoland/rev/0edab0f8fa94
Add a test for the scenario being fixed. r=botond
Regressions: 1622444
Regressions: 1622445
Regressions: 1622449
Flags: qe-verify+
QA Whiteboard: [qa-76b-p2]
QA Whiteboard: [qa-76b-p2]

Successfully reproduced the issue on Firefox Nightly 75.0a1 (2020-02-22) under macOS 10.15 using the STR provided in Comment 0.

The issue is no longer reproducible on latest Nightly 77.0a1 (2020-04-15) and Firefox 76.0b5. Tests were performed on Windows 10 (x64), Ubuntu 18.04 (x64) and macOS 10.15.

Status: RESOLVED → VERIFIED
Flags: qe-verify+
Regressions: 1636911
See Also: → 1690697
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: