RESOLVED FIXED 42390
Multi-layer backgrounds repaint (in low quality) every 0.5 seconds
https://bugs.webkit.org/show_bug.cgi?id=42390
Summary Multi-layer backgrounds repaint (in low quality) every 0.5 seconds
Andreas Kling
Reported 2010-07-15 11:38:29 PDT
ImageQualityController (in RenderBoxModelObject.cpp) is broken for multi-layer backgrounds. Since it only remembers the RenderBoxModelObject* and what IntSize the tile was, an element with multiple layers will get caught by the "animated resize" heuristic and get stuck in a loop where it's repainted in low quality every 0.5 seconds. This can be observed with LayoutTests/fast/backgrounds/size/contain-and-cover.html
Attachments
Proposed patch (12.00 KB, patch)
2010-07-15 11:42 PDT, Andreas Kling
no flags
Proposed patch (1.77 KB, patch)
2010-07-15 11:48 PDT, Andreas Kling
no flags
Patch (4.02 KB, patch)
2010-10-20 07:59 PDT, Balazs Kelemen
no flags
Testcase (663 bytes, text/html)
2010-10-20 12:30 PDT, Simon Fraser (smfr)
no flags
Patch (5.62 KB, patch)
2010-11-12 13:00 PST, Stephen White
no flags
Patch (9.76 KB, patch)
2010-11-12 14:10 PST, Stephen White
simon.fraser: review+
Andreas Kling
Comment 1 2010-07-15 11:42:58 PDT
Created attachment 61694 [details] Proposed patch Skip the shouldPaintAtLowQuality() check for layers with siblings.
WebKit Review Bot
Comment 2 2010-07-15 11:46:19 PDT
Attachment 61694 [details] did not pass style-queue: Failed to run "['WebKitTools/Scripts/check-webkit-style']" exit_code: 1 Total errors found: 0 in 0 files If any of these errors are false positives, please file a bug against check-webkit-style.
Andreas Kling
Comment 3 2010-07-15 11:48:02 PDT
Created attachment 61696 [details] Proposed patch
Simon Fraser (smfr)
Comment 4 2010-07-15 15:15:26 PDT
Why aren't the authors of ImageQualityController copied on this bug?
Andreas Kling
Comment 5 2010-07-16 02:51:08 PDT
(In reply to comment #4) > Why aren't the authors of ImageQualityController copied on this bug? Sorry about that, I was leaving in a hurry last night. Thank you for adding :-)
Stephen White
Comment 6 2010-07-16 08:47:39 PDT
Looks good to me (though I'm not a reviewer). I checked this against the benchmarks my the original patch, and there were no regressions.
Mark Rowe (bdash)
Comment 7 2010-07-16 16:42:43 PDT
Simon Fraser (smfr)
Comment 8 2010-07-16 16:57:36 PDT
Does this affect some live sites? Can you post a testcase?
Andreas Kling
Comment 9 2010-07-16 17:07:08 PDT
(In reply to comment #8) > Does this affect some live sites? Can you post a testcase? I have not seen this on any live sites, but it's not unlikely. I stumbled upon this problem while working on bug 41201. Like I said, you can observe this with the in-tree layout test LayoutTests/fast/backgrounds/size/contain-and-cover.html. If you resize that page, only the first <div> will be repainted in high quality after 500ms. The rest are repainted in low quality. This repeats every 500ms.
Darin Adler
Comment 10 2010-08-29 11:42:03 PDT
Comment on attachment 61696 [details] Proposed patch This seems more like a workaround than a fix. Just turns off the logic for layers that have a next pointer, with no comment or indication in the code why, and no regression test. We can do better. > - bool useLowQualityScaling = shouldPaintAtLowQuality(context, image, tileSize); > + bool useLowQualityScaling; > + if (bgLayer->next()) > + useLowQualityScaling = false; > + else > + useLowQualityScaling = shouldPaintAtLowQuality(context, image, tileSize); I think the logic would be easier to read like this: bool useLowQualityScaling = !bgLayer->next() && shouldPaintAtLowQuality(context, image, tileSize); But still, we need an explanation for why we should paint multiple layer backgrounds always in high quality.
Andreas Kling
Comment 11 2010-09-01 08:14:42 PDT
(In reply to comment #10) > (From update of attachment 61696 [details]) > This seems more like a workaround than a fix. Just turns off the logic for layers that have a next pointer, with no comment or indication in the code why, and no regression test. We can do better. You are completely right. @Stephen: You hacked a bunch on ImageQualityController - could you have a closer look at this?
Simon Fraser (smfr)
Comment 12 2010-09-08 13:13:40 PDT
Stephen: ping!
Stephen White
Comment 13 2010-09-16 11:40:43 PDT
(In reply to comment #12) Sorry; was on vacation. Taking a look now.
Stephen White
Comment 14 2010-09-16 11:59:00 PDT
I can't repro this on r67642 using Safari, nor Chrome or Chrome's test_shell. Andreas, is there some other way I can reproduce this? The code still looks ok to me, but I don't know much about multi-image backgrounds, to be honest. I did see some similar problems in earlier versions of ImageQualityController, when each image had its own timer (when two images were overlapping, one image's expiring timer would trigger another image's timer to start, resulting in toggling qualities), but when the timers were unified, those problems went away.
Andreas Kling
Comment 15 2010-09-16 12:06:14 PDT
(In reply to comment #14) > I can't repro this on r67642 using Safari, nor Chrome or Chrome's test_shell. Andreas, is there some other way I can reproduce this? Just repro'd on ToT Qt. Are you sure that you can't reproduce? Perhaps it's just more apparent on Qt since the difference between low and high quality scaling is very noticeable with QPainter.
Stephen White
Comment 16 2010-09-16 14:33:22 PDT
(In reply to comment #15) > (In reply to comment #14) > > I can't repro this on r67642 using Safari, nor Chrome or Chrome's test_shell. Andreas, is there some other way I can reproduce this? > > Just repro'd on ToT Qt. Are you sure that you can't reproduce? Perhaps it's just more apparent on Qt since the difference between low and high quality scaling is very noticeable with QPainter. Hmm, I still can't see the difference visually, but setting some breakpoints reveals that the timer is definitely firing repeatedly. (Chrome has some further criteria for drawing high quality in platform/graphics/skia which may be obscuring the result, although it's usually pretty easy to see in Safari). It definitely looks like there are some ping-pong effects going on here. I don't know how much time I'll have to look into this just now, so if you want to go ahead and commit your patch in the interim (with the fixes Darin suggested), I'm ok with that. Perhaps leave a comment suggesting that this is only an interim fix until we track down why it's ping-ponging in this case.
Simon Fraser (smfr)
Comment 17 2010-09-16 14:38:08 PDT
I don't think the patch makes any sense, so I don't think we should commit it.
Balazs Kelemen
Comment 18 2010-10-18 09:12:01 PDT
I have created a somewhat simpler test case that triggers the bug: http://gist.github.com/632183. The interesting thing is that I could not trigger it with only one box that has two images but just when I added another. Maybe the root of the problem is that we have only one global timer for all box objects.
Balazs Kelemen
Comment 19 2010-10-18 09:14:41 PDT
D'oh, I pushed it with one div, so you should add the other to trigger the bug.
Balazs Kelemen
Comment 20 2010-10-20 07:59:08 PDT
Balazs Kelemen
Comment 21 2010-10-20 08:08:02 PDT
Unfortunately I could not create a test case for this. I have tried it on Mac and Windows but it seems like only Qt has the visual difference. Inside the debugger I have seen that the repainting has happened in every 0.5 sec on those platforms as well.
Simon Fraser (smfr)
Comment 22 2010-10-20 11:40:35 PDT
Won't this patch still cause low-quality painting if the same image is used several times in a CSS background?
Simon Fraser (smfr)
Comment 23 2010-10-20 12:30:21 PDT
Created attachment 71320 [details] Testcase
Simon Fraser (smfr)
Comment 24 2010-10-20 12:34:06 PDT
Comment on attachment 71295 [details] Patch Patch does not fix the attached testcase.
Simon Fraser (smfr)
Comment 25 2010-10-20 13:04:27 PDT
To get this right I think you really need to know what it is that's drawing the image. You don't care if the same image is being drawn for different reasons at different sizes, you care about whether the image is being resized for this one particular use.
Stephen White
Comment 26 2010-11-12 12:49:36 PST
The problem seems to be that, since background-image allows more than one URL per element, neither the Image nor the RenderBoxModelObject (element) alone are enough to uniquely identify the object being drawn. I've put together a patch that replaces the RenderBoxModelObject* key with an {Object, Image} pair, which seems to fix the problem. Let me know what you guys think.
Stephen White
Comment 27 2010-11-12 13:00:33 PST
Simon Fraser (smfr)
Comment 28 2010-11-12 13:01:33 PST
Doesn't that still have issues if the same image is used multiple times in background-image?
WebKit Review Bot
Comment 29 2010-11-12 13:03:37 PST
Eric Seidel (no email)
Comment 30 2010-11-12 13:14:05 PST
Eric Seidel (no email)
Comment 31 2010-11-12 13:39:13 PST
Stephen White
Comment 32 2010-11-12 14:08:38 PST
(In reply to comment #28) > Doesn't that still have issues if the same image is used multiple times in background-image? You're right. That won't work for your test case above. I'm trying another version which includes the bgLayer pointer as part of the key. This should basically represent the "role" of the image in the background-image. Ideally, it should just be an index (int), but I couldn't find an easy way to do that, so I've made it a void*, to discourage ImageQualityController from dereferencing it (it should only be used for hashing).
Stephen White
Comment 33 2010-11-12 14:10:54 PST
Stephen White
Comment 34 2010-11-15 10:06:28 PST
(In reply to comment #33) > Created an attachment (id=73776) [details] > Patch For your consideration. ;) (see above)
Stephen White
Comment 35 2010-11-18 04:25:52 PST
Landed as r72282. Closing bug (manually, since webkit-patch got confused).
Pavel Feldman
Comment 36 2010-11-22 02:23:54 PST
Needed to roll devtools' part out. Were you landing this manually? M WebKit/chromium/ChangeLog M WebKit/chromium/src/js/devTools.css Committed r72511
Stephen White
Comment 37 2010-11-22 04:47:12 PST
(In reply to comment #36) > Needed to roll devtools' part out. Were you landing this manually? Sorry, don't know how that snuck in there. (Yes, I landed this manually.)
Note You need to log in before you can comment on or make changes to this bug.