Open Bug 546362 Opened 14 years ago Updated 2 years ago

Animating the position of an absolutely positioned element inside a float repaints too much

Categories

(Core :: Layout: Block and Inline, defect)

defect

Tracking

()

People

(Reporter: guitarist198, Unassigned)

References

()

Details

Attachments

(2 files)

User-Agent:       Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6
Build Identifier: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6

OS: Mac OS X 10.6.2
Browser: Firefox 3.6

I have noticed that when doing animations (moving an item across the screen), at times the animations are choppy in firefox.  It is hard to explain how to reproduce this problem as it seems it is dependent on random elements of the page.  I have tested the same page in Opera, Safari and IE and the animations are very smooth.

The following is a pseudo-code representation of the setup I have:
Copy code

   1. <div id="container">
   2.         <div id="header"></div>
   3.         <div id="mainsection">
   4.                 <div id="nav" width:30%; height:100%; float:left;></div>
   5.                 <div id="content" float:left; width:70%;></div>
   6.         </div>
   7. </div>

If I put the code block anywhere but inside the content div, the animation is smooth.  However once put where it belongs, the animation becomes choppy in firefox. 

I was playing around a bit and found out that doing some random changes causes the animations to become smooth.  For instance, removing height:100% on the nav makes the animations in the content div smooth.  I lucked out with this as it doesnt change the layout of the website at all.  Another solution I found is that if I remove the box shadows I have on the mainsection the animations become smooth.  These attributes are no problem for Safari and Opera though.

I recently rewrote the plugin I was working on and ran into this problem again.  However, removing the height:100% trick did not work.

 

Reproducible: Always

Steps to Reproduce:
Please refer to the details section for steps to reproduce, as its not an easy set of steps to reproduce (not sure what the exact cause is)
Actual Results:  
Choppy Animation

Expected Results:  
Smooth Animation
The box shadows are the real cause for the bad performance.

> For instance, removing height:100% on the nav
> makes the animations in the content div smooth.

I can't confirm this.

Bug 544099 might improve the performance in this testcase.
Yes, I should have mentioned that particular solution does not apply to the example website that I provided.  It had only worked in one situation on an older plugin that I used.

Thanks for the quick reply.
(In reply to comment #1)
> Bug 544099 might improve the performance in this testcase.

Hmm, probably not. For some reason your animation triggers a repaint of almost the whole page, starting at the "Nav Section" text. I haven't checked what causes the repaint.
I recently updated the test page to contain a button that allows you to toggle the box shadows.  Turning off the box shadows allows one to see the smooth animations.  I'd assume the repaint isn't across the whole page in that case.

http://idiotbox07.awardspace.biz/testing/
Hmm I just got the paints plugin for firebug and even though the animations are smooth after turning off the shadows, the paints still seem to be as you described them, across the whole page starting at the nav section text.
Well I don't mean to spam this bug but I updated yet again with some more findings.  I reduced some of the divs wrapping the animated plug, leaving only one, the content div.  I then added a button that when pressed sets its float to none as it is current set to float left.  

First examine repaints without pressing any of the buttons.  You will see repaints across full screen width.  If you just press the button to remove the floating, the animations become smooth and repaints becomes more localized.  This differs from removing shadows as doing so produces smooth animations but repaints are still large.
I'm a web developer and I have also been experiencing this problem.
(In reply to comment #6)
> Well I don't mean to spam this bug

No worries. We can use this bug for debugging and another bug for the actual fixing.

> If you just press the button to remove the
> floating, the animations become smooth and repaints becomes more localized.

That's interesting. So one of the things you animate cause too large repaints if the box is floated. Can you try to reduce the animated properties (e.g. "opacity" and "left") and find out which one is responsible? It would be great to have a minimal testcase.
 
> This differs from removing shadows as doing so produces smooth animations but
> repaints are still large.

Yeah, large repaints are only a problem if it's expensive to draw the affected areas. Drawing shadows is extremely expensive, drawing borders and background colors is not.

(In reply to comment #7)
> I'm a web developer and I have also been experiencing this problem.

Which problem? Too large repaints or slow shadow painting?
Okay, I added a few more pages for debugging and testing:
http://idiotbox07.awardspace.biz/testing/index.html
   This has both opacity and left animations

http://idiotbox07.awardspace.biz/testing/left-only.html
   Only has the filmstrip (ie only left animation)

http://idiotbox07.awardspace.biz/testing/opacity-only.html
   Only has the panelbox (ie only opacity animation)

It seems that opacity does not cause any problems.  The animations are smooth with or without both shadows and floating container.  The odd point that I noticed is that with any combination of shadows, float, ect, I could not produce a result in which the repaints were localized.  If you look at the index.html page repaints by first disabling float left, you will see that the repaints are localized basically to the panel and the filmstrip only.  However in the opacity-only, the most localized repaint I can achieve with the current toggles is a repaint of the container div.

The left-only page produces choppy animations.  Disabling shadows or float both produce smooth animations, yet again, the repaints are not as localized as the index page.  They are localized to the container div only.

From these tests it would seem that the position based animations are at fault.
Depends on: 544099
Component: General → Layout: R & A Pos
OS: Mac OS X → All
Product: Firefox → Core
QA Contact: general → layout.r-and-a-pos
Hardware: x86 → All
Summary: Animations in firefox are choppy due to seemingly unrelated tags and/or attributes → Animating the position of an absolutely positioned element repaints too much
Version: unspecified → Trunk
This is actually a block issue.  The problem is that if the container for the stuff being moved if floated, then it's on an inline line, not a block one.

And if we have to reflow an inline line we always invalidate the whole thing, no matter what actually changed.  See nsBlockFrame::ReflowLine the second branch of the toplevel if statement.

We could optimize this in various ways, I think; the question is whether it's worth it or whether we should just focus on a saner invalidation setup.
Status: UNCONFIRMED → NEW
Component: Layout: R & A Pos → Layout: Block and Inline
Ever confirmed: true
QA Contact: layout.r-and-a-pos → layout.block-and-inline
Summary: Animating the position of an absolutely positioned element repaints too much → Animating the position of an absolutely positioned element inside a float repaints too much
The URLs for the testcases no longer work. Can anyone provide a new URL or upload a testcase to this bug?
Blocks: 716747
Depends on: dlbi
(In reply to Timothy Nikkel (:tn) from comment #12)
> The URLs for the testcases no longer work. Can anyone provide a new URL or
> upload a testcase to this bug?

The slideshow from bug 693105 (which also depends on bug 539356) at 
http://www.bblopers.nl/zo-trainen-wij/hoe-trainen-wij might be a URL to use or extract a testcase from.
Blocks: 723599
Attached file Test-case
This is based on the slideshow mentioned in comment 13.

Since animation is contained inside the blue div-element (that have overflow:hidden), nothing outside it should probably be repainted. But using nglayout.debug.paint_flashing reveals, that the bounding box of the two floated, green div-elements are repainted.

Another problem (separate bug?) is that animating the opacity, will in some cases consistently cause repaints of the parts of the animated-element that is outside the blue div-element. This repaint seem to be delayed about half a second after the change occurs and is perhaps easier to see if the movement is turned off. E.g. switching opacity between 0 and 1 will not show the problem, but switching from 0 to.5 and from 1 to .3 will (switching back will also cause the delayed repaint but only within the blue div).
Attachment #603695 - Attachment mime type: text/plain → text/html
To follow up on comment #14 after dlbi has landed, it seems the behavior has changed, such that now only the animated element is repainted. But the part of the animated element that is outside the blue element is also repainted, now on every frame, even though it should be clipped.
Depends on: 770001
Thanks for the testcase!

The half a second delay is the timeout for when we transition the opacity layer into an inactive state. So this ended up testing active, inactive and the transitions between them, caught a lot of edge cases.

I've revived an old patch in bug 7700001 and fixed all the edge cases that this found. This bug should be fixed once that lands.
Attached patch MochitestSplinter Review
Attachment #671330 - Flags: review?(roc)
Testing Aurora 19 (and on the latest nightly) it seems that only the animated element is repainted as in Aurora 18 (which is good). But the part of the animated element that is outside the blue element is still repainted. Not on every frame as in Aurora 18, but about 3 times per loop similar to the behavior described in comment 14 from before DLBI landed.
Comment on attachment 671330 [details] [diff] [review]
Mochitest

Review of attachment 671330 [details] [diff] [review]:
-----------------------------------------------------------------

::: layout/base/tests/invalidation/test_abs_pos_opacity.html
@@ +31,5 @@
> +  if (count > 50) {
> +    SimpleTest.finish();
> +    return;
> +  }
> +  var t = (new Date().getTime() % 5000) / 5000; // one loop per 5 seconds

The entire test is likely to finish in less than 1 seconds if we hit 60 frames per second.

Maybe you should simplify this by just letting t run freely and just end if more than one second has elapsed. Although to be honest I'd prefer the test to be shorter. Maybe half a second.
Severity: normal → S3
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: