Bug 89475

Summary: Blur filter causes issues when scrolling
Product: WebKit Reporter: Keyar Hood <keyar>
Component: CSSAssignee: Alexandru Chiculita <achicu>
Status: RESOLVED FIXED    
Severity: Normal CC: achicu, dglazkov, dino, jamesr, keyar, mitz, senorblanco, shanestephens, simon.fraser, thorton, webkit.review.bot
Priority: P2    
Version: 528+ (Nightly build)   
Hardware: Unspecified   
OS: Unspecified   
Bug Depends on: 90091    
Bug Blocks:    
Attachments:
Description Flags
Demonstrates the scrolling blur bug. No red should be visible if the scrolling worked.
none
Patch V1
webkit.review.bot: commit-queue-
Archive of layout-test-results from ec2-cr-linux-01
none
Patch V2
simon.fraser: review+, simon.fraser: commit-queue-
Patch V3 none

Description Keyar Hood 2012-06-19 08:37:36 PDT
Created attachment 148340 [details]
Demonstrates the scrolling blur bug. No red should be visible if the scrolling worked.

Having blur on the entire page will result in incorrect rendering when the page is scrolled if one div is scrolled underneath another.

Set a <div> tag set to use "-webkit-filter: blur(#px)" where # is any number, including zero.
Within this div, have two divs such that one will scroll underneath the other (such as having one with fixed position). Give the child divs two separate background colours.
Scroll the page and the rendering will be incorrect. See attached file for an example page that displays this problem (if there was no issue, the page will not have red).
Comment 1 Keyar Hood 2012-06-19 10:54:52 PDT
Note, the supplied test will not automatically work on Mac. You will have to manually scroll up then down to see the problem
Comment 2 Shane Stephens 2012-06-20 21:09:01 PDT
At least on the mac, this seems to be an issue more with failure to repaint rather than the scroll not working?
Comment 3 Alexandru Chiculita 2012-06-21 11:43:32 PDT
I think this happens because of the subpixel layout. The issue doesn't seem to reproduce in Safari. I think that adding some pixelSnappedIntRect would fix the issue. I will take a look.
Comment 4 Alexandru Chiculita 2012-06-21 18:16:48 PDT
Sorry I was looking at the wrong Chromium build. The real issue is that Chromium is doing a blit when scrolling instead of repainting the area. I think we need disable scrolling by blitting when there are elements with filters. We only need to do that for blur and drop-shadow (filters with outsets).
Comment 5 Stephen White 2012-06-22 07:16:31 PDT
(In reply to comment #3)
> I think this happens because of the subpixel layout. The issue doesn't seem to reproduce in Safari. I think that adding some pixelSnappedIntRect would fix the issue. I will take a look.

Just FYI, I was able to repro this in Safari (WebKit nightly), although it may not be captured by this test case.  Simply open Facebook or Google+, apply a -webkit-filter: blur(1px); to the <body> element, and scroll.
Comment 6 Alexandru Chiculita 2012-06-22 09:49:24 PDT
(In reply to comment #5)
> (In reply to comment #3)
> > I think this happens because of the subpixel layout. The issue doesn't seem to reproduce in Safari. I think that adding some pixelSnappedIntRect would fix the issue. I will take a look.
> 
> Just FYI, I was able to repro this in Safari (WebKit nightly), although it may not be captured by this test case.  Simply open Facebook or Google+, apply a -webkit-filter: blur(1px); to the <body> element, and scroll.

You're right. I was trying in a Chrome Dev build and the only thing I've seen were some white lines around the repaint rectangles, so I thought it was from the subpixel. That issue seems to be fixed in the nightly.

The current issue is from the the FrameView scrolling mechanism which is trying to move things around while scrolling instead of repainting. That only happens when it is possible to be done, but in this case it is not possible.

I will post a patch today.
Comment 7 Alexandru Chiculita 2012-06-22 13:44:38 PDT
Created attachment 149094 [details]
Patch V1

Not the final patch, I'm using the EWS to collect the expected results.
Comment 8 WebKit Review Bot 2012-06-22 16:11:37 PDT
Comment on attachment 149094 [details]
Patch V1

Attachment 149094 [details] did not pass chromium-ews (chromium-xvfb):
Output: http://queues.webkit.org/results/13029545

New failing tests:
css3/filters/blur-filter-page-scroll.html
Comment 9 WebKit Review Bot 2012-06-22 16:11:53 PDT
Created attachment 149129 [details]
Archive of layout-test-results from ec2-cr-linux-01

The attached test failures were seen while running run-webkit-tests on the chromium-ews.
Bot: ec2-cr-linux-01  Port: <class 'webkitpy.common.config.ports.ChromiumXVFBPort'>  Platform: Linux-2.6.35-28-virtual-x86_64-with-Ubuntu-10.10-maverick
Comment 10 Alexandru Chiculita 2012-06-25 13:50:52 PDT
Created attachment 149346 [details]
Patch V2
Comment 11 Simon Fraser (smfr) 2012-06-25 14:48:16 PDT
Comment on attachment 149346 [details]
Patch V2

View in context: https://bugs.webkit.org/attachment.cgi?id=149346&action=review

> LayoutTests/ChangeLog:15
> +        * platform/chromium-linux/css3/filters/blur-filter-page-scroll-expected.png: Added.
> +        * platform/chromium-linux/css3/filters/blur-filter-page-scroll-expected.txt: Added.
> +        * platform/chromium-mac/css3/filters/blur-filter-page-scroll-expected.png: Added.
> +        * platform/chromium-mac/css3/filters/blur-filter-page-scroll-expected.txt: Added.

Are these platforms not using mock scrollbars? The images show platform scrollbars, which is bad.
Comment 12 Alexandru Chiculita 2012-06-25 17:28:27 PDT
(In reply to comment #11)
> (From update of attachment 149346 [details])
> View in context: https://bugs.webkit.org/attachment.cgi?id=149346&action=review
> 
> > LayoutTests/ChangeLog:15
> > +        * platform/chromium-linux/css3/filters/blur-filter-page-scroll-expected.png: Added.
> > +        * platform/chromium-linux/css3/filters/blur-filter-page-scroll-expected.txt: Added.
> > +        * platform/chromium-mac/css3/filters/blur-filter-page-scroll-expected.png: Added.
> > +        * platform/chromium-mac/css3/filters/blur-filter-page-scroll-expected.txt: Added.
> 
> Are these platforms not using mock scrollbars? The images show platform scrollbars, which is bad.

If they do, I don't know how to trigger them. This is what the new-run-webkit-test generated. Do you know how to generate that?

I didn't do anything special for WebKit Mac to use the mock scrollbars.
Comment 13 Simon Fraser (smfr) 2012-06-25 17:33:56 PDT
Maybe those ports haven't enabled mock scrollbars in DRT yet. They should!
Comment 14 Alexandru Chiculita 2012-06-26 11:37:06 PDT
(In reply to comment #13)
> Maybe those ports haven't enabled mock scrollbars in DRT yet. They should!

I've asked on IRC and it seems like there's a window.internals API that enables mock scrollbars. I will use that and post a new patch.
Comment 15 Alexandru Chiculita 2012-06-26 16:58:41 PDT
Created attachment 149635 [details]
Patch V3

Updated the test to use the mock scrollbars on all the platforms.
Comment 16 WebKit Review Bot 2012-06-27 10:38:23 PDT
Comment on attachment 149635 [details]
Patch V3

Clearing flags on attachment: 149635

Committed r121348: <http://trac.webkit.org/changeset/121348>
Comment 17 WebKit Review Bot 2012-06-27 10:38:29 PDT
All reviewed patches have been landed.  Closing bug.
Comment 18 Simon Fraser (smfr) 2012-06-27 10:52:55 PDT
Comment on attachment 149635 [details]
Patch V3

View in context: https://bugs.webkit.org/attachment.cgi?id=149635&action=review

> Source/WebCore/page/FrameView.cpp:1473
> +        if (renderBox->layer() && renderBox->layer()->parent()) {
> +            RenderBoxModelObject* renderer = renderBox->layer()->parent()->renderer();
> +            if (renderer->style()->hasFilterOutsets()) {
> +                // If the fixed layer has a blur/drop-shadow filter applied on its parent, we cannot 
> +                // scroll using the fast path, otherwise the outsets of the filter will be moved around the page.
> +                return false;
> +            }
> +        }

Actually, doesn't this have to check all ancestors?
Comment 19 Alexandru Chiculita 2012-06-27 11:28:11 PDT
(In reply to comment #18)
> (From update of attachment 149635 [details])
> View in context: https://bugs.webkit.org/attachment.cgi?id=149635&action=review
> 
> > Source/WebCore/page/FrameView.cpp:1473
> > +        if (renderBox->layer() && renderBox->layer()->parent()) {
> > +            RenderBoxModelObject* renderer = renderBox->layer()->parent()->renderer();
> > +            if (renderer->style()->hasFilterOutsets()) {
> > +                // If the fixed layer has a blur/drop-shadow filter applied on its parent, we cannot 
> > +                // scroll using the fast path, otherwise the outsets of the filter will be moved around the page.
> > +                return false;
> > +            }
> > +        }
> 
> Actually, doesn't this have to check all ancestors?

Yes it seems like it needs to check all the ancestors. I've added https://bugs.webkit.org/show_bug.cgi?id=90087 to fix that.