Closed
Bug 635035
Opened 14 years ago
Closed 14 years ago
ThebesLayerBuffer can compute the wrong quadrant to draw into with non-identity resolution, should support self-copies for image surfaces
Categories
(Core :: Layout, defect)
Core
Layout
Tracking
()
RESOLVED
FIXED
Tracking | Status | |
---|---|---|
fennec | 2.0+ | --- |
People
(Reporter: stechz, Assigned: cjones)
References
Details
Attachments
(11 files, 4 obsolete files)
2.02 KB,
patch
|
Details | Diff | Splinter Review | |
5.59 KB,
patch
|
mattwoodrow
:
review+
|
Details | Diff | Splinter Review |
2.22 KB,
patch
|
roc
:
review+
|
Details | Diff | Splinter Review |
4.02 KB,
patch
|
roc
:
review+
|
Details | Diff | Splinter Review |
1.85 KB,
patch
|
roc
:
superreview+
|
Details | Diff | Splinter Review |
1.35 KB,
patch
|
roc
:
review+
|
Details | Diff | Splinter Review |
3.95 KB,
patch
|
roc
:
superreview+
|
Details | Diff | Splinter Review |
4.57 KB,
patch
|
roc
:
review+
|
Details | Diff | Splinter Review |
2.55 KB,
patch
|
roc
:
superreview+
|
Details | Diff | Splinter Review |
4.53 KB,
patch
|
Details | Diff | Splinter Review | |
161.77 KB,
image/png
|
Details |
When panning in Fennec, the Thebes buffer will change frequently because of small changes in the visible region that defines its dimensions. This is bad on Fennec, because it causes frequent reallocations that result in fragmentation. The jumpy numbers are caused by setting the visible region in FrameLayerBuilder: http://mxr.mozilla.org/mozilla-central/source/layout/base/FrameLayerBuilder.cpp#938 Which is a direct result of unioning all the display items together: http://mxr.mozilla.org/mozilla-central/source/layout/base/FrameLayerBuilder.cpp#1057 We either need to stabilize the visible region, or not realloc buffers when the visible region slightly changes in ThebesLayerBuffer.
Updated•14 years ago
|
Updated•14 years ago
|
tracking-fennec: --- → 2.0+
The buffer can be any size you want as long as it contains the visible region. So we shouldn't mess with the visible region, but instead change the buffer allocation strategy.
Comment 2•14 years ago
|
||
very hard to reproduce on the desktop. very easy to reproduce on android. maybe android specific.
Assignee | ||
Comment 3•14 years ago
|
||
On any sites in particular?
Comment 4•14 years ago
|
||
i have been using news.google.com, zooming into a small area of text, and panning up and down. I rebuilt desktop with MOZ_GFX_OPTIMIZE_MOBILE enabled and think I can see the problem -- it isn't as obvious as on android. I think it is this change (but probably should verify tomorrow) http://mxr.mozilla.org/mozilla-central/source/layout/base/nsPresShell.cpp#5322
Assignee | ||
Comment 5•14 years ago
|
||
That code isn't on the "normal" painting path, it's what we use for drawWindow(), so I wouldn't expect that to affect displayport stuff.
Updated•14 years ago
|
Assignee: nobody → crowderbt
Comment 6•14 years ago
|
||
Assignee | ||
Comment 7•14 years ago
|
||
FWIW, you can get similar output in a debug build with NSPR_LOG_MODULES="Layers:5" fennec 2>&1 | grep 'buffer(x2)'
Assignee | ||
Comment 8•14 years ago
|
||
Loading google.com, I get -254924480[1744a60]: BasicShadowableThebes(1ee81e0): creating 480 x 800 buffer(x2) -254924480[1744a60]: BasicShadowableThebes(1e11f60): creating 481 x 800 buffer(x2) and a similar effect in landscape 589527360[18f8a60]: BasicShadowableThebes(1f18eb0): creating 800 x 500 buffer(x2) 589527360[18f8a60]: BasicShadowableThebes(1f08b90): creating 800 x 501 buffer(x2) These look like reallocs due to rounding buffer sizes out instead of to the nearest pixel. See also bug 634759 comment 10. If the frontend is already trying to set up resolution/displayport so as to get round device pixels, but missing just slightly from precision issues, I don't see a problem off-hand with rounding to the nearest pixel instead of rounding out.
Reporter | ||
Comment 9•14 years ago
|
||
Frontend is sending the exact same numbers on every displayport update, so rounding out or rounding in won't matter. f(x) is always f(x), whether f is round, floor, or ceil. Please see comment #1.
Assignee | ||
Comment 10•14 years ago
|
||
The effect I see on google.com is, load page and alloc, then autofit and realloc. The frontend can't be using the same combination of resolution/displayport (AFAIK), but indeed the resize could be due to a display list change instead of a rounding discrepancy. But as I write this, I just remembered that we throw out buffers on resolution changes regardless of whether the buffer size would change, so this is a moot point. I'm seeing more interesting results on the desktop version of news.google.com, looking.
Assignee | ||
Comment 11•14 years ago
|
||
Here's the general pattern I'm seeing panning up and down news.google.com, keeping resolution the same -410846912[16dfa60]: BasicShadowableThebes(22e9900): creating 529 x 1601 buffer(x2) -410846912[16dfa60]: ThebesLayerBuffer(22e9aa0): surface can't self-copy, throwing out buffer(x2) -410846912[16dfa60]: BasicShadowableThebes(22e9900): creating 529 x 1601 buffer(x2) -410846912[16dfa60]: BasicShadowableThebes(22e9900): creating 529 x 1603 buffer(x2) -410846912[16dfa60]: ThebesLayerBuffer(22e9aa0): surface can't self-copy, throwing out buffer(x2) -410846912[16dfa60]: BasicShadowableThebes(22e9900): creating 529 x 1601 buffer(x2) -410846912[16dfa60]: ThebesLayerBuffer(22e9aa0): surface can't self-copy, throwing out buffer(x2) -410846912[16dfa60]: BasicShadowableThebes(22e9900): creating 529 x 1601 buffer(x2) -410846912[16dfa60]: BasicShadowableThebes(22e9900): creating 529 x 1603 buffer(x2) I'm not sure why we're fluctuating between h=1601 and h=1603, might be display-list monkeyshine. That's not a huge deal though in this case, because once we get a h=1603 buffer we should be keeping it. The inability of gfxImageSurface to self-copy is causing us to discard the buffer. Might need to fix, will poke a bit more.
Assignee | ||
Comment 12•14 years ago
|
||
(I realized over dinner that I haven't pulled from m-b in a while, like a month. Might change things a bit.)
Assignee | ||
Comment 13•14 years ago
|
||
Brian, I have some ideas for this, going to steal unless you object ;).
Assignee: crowderbt → jones.chris.g
Assignee | ||
Comment 14•14 years ago
|
||
The vast majority of the buffer reallocs on news.google.com were coming from thebes buffers trying to self-copy, but failing with image surfaces. Fixing the lack of self-copy in pixman looks like a lost cause, judging by the code; I don't believe self-copies can be supported in the SIMD fast-paths without either deoptimizing the current code (uh-uh) or adding a slower path most users seem not to need. We can fix this outside of pixman though, I'll look into that if it's a win over this impl. Anyway, this patch compromises by "self-copying" through a temporary surface and back to the original surface. This is strictly cheaper and less memory-intensive than allocating a new shmem buffer pair (in theory).
Assignee | ||
Comment 15•14 years ago
|
||
The other source of reallocs when panning up and down news.google.com was 1-3 pixel jitter in buffer dimensions. With the previous patch, we do OK because when we jitter larger a bit, we can keep the larger size permanently. But this patch eliminates the jitter for simple panning. It would also help (though not much) with pages that grow a bit or whatever. It's probably worth fixing the jitter on its own. There's also some more buffer churn I don't understand yet.
Assignee | ||
Comment 16•14 years ago
|
||
If anyone has a chance to try these out, I'd really appreciate it. WIP because they need a lot of manual testing :/.
(In reply to comment #14) > The vast majority of the buffer reallocs on news.google.com were coming from > thebes buffers trying to self-copy, but failing with image surfaces. Fixing > the lack of self-copy in pixman looks like a lost cause, judging by the code; I > don't believe self-copies can be supported in the SIMD fast-paths without > either deoptimizing the current code (uh-uh) or adding a slower path most users > seem not to need. Last time I looked, it didn't seem that bad. Vertical scrolling, which is the case we mostly care about, just turns into memmove. Horizontal scrolling by more than 4 pixels should be fine with SIMD too.
Assignee | ||
Comment 18•14 years ago
|
||
I wasn't claiming that the self-copy impl is hard, just that it appears to me that integrating it into pixman would result in code that the pixman people wouldn't be interested in. Worth another look though if/when we want self-copies.
Reporter | ||
Comment 19•14 years ago
|
||
What about writing a small NEON-optimized version for our specific case here?
Assignee | ||
Comment 20•14 years ago
|
||
That's of course possible. The order of things I want to fix is (1) Stop churning shmem on large scrolls (2) [if the copy-through-tmp-surface shows up in profiles] Implement simple self-copying of gfxImageSurface in C (3) [if the pure-C self-copy shows up in profiles] Consider SIMD-ized variants I doubt (2) will be worth doing until bug 634397, because I saw a lot of shifting displayport while panning that looked like bug 624451. (Cool stuff, BTW!) I think (3) is a bit down the line, and might not ever be worth doing since memcpy/memmove are supposed to use SIMD themselves. Sometimes that's even true.
I vote for option 2. For vertical scrolling you can use a single memmove() to do the entire copy, and the C library should have an optimal implementation of memmove().
Assignee | ||
Comment 22•14 years ago
|
||
Not in general, but for the cases we care about we can do that.
Assignee | ||
Comment 24•14 years ago
|
||
(This problem has been around for a while, but I figured I'd just fix it here.) I was seeing problems with front->back readback trying to update a bogus gfxContext for the newly-painted quadrant. The reason turned out to be that ExtendForScaling() on the draw region moved the draw bounds outside of the ThebesLayerBuffer's buffer rect. I don't understand the ExtendForScaling() code very well, but we do need to a gfxContext covering the same pixels in PaintBuffer() as the one updated during readback. Since ThebesLayerBuffer::BeginPaint() asks for a context covering the un-extended draw region, this patch shifts things around so we ask for a quadrant for readback that covers the same bounds.
Attachment #514748 -
Attachment is obsolete: true
Attachment #514749 -
Attachment is obsolete: true
Attachment #515244 -
Flags: review?(matt.woodrow+bugzilla)
Assignee | ||
Comment 25•14 years ago
|
||
(This is another pre-existing bug that I found while debugging my patches here.) The problem here is that both mBufferRect *and* neededRegion.GetBounds() can be sized properly for the current buffer if there's scaling. If neededRegion.GetBounds() happens to be larger than mBufferRect, then we end using the wrong, smaller size and messing up other calculations. This patch keeps the don't-shrink-mBufferRect logic intact and deals with the edge-case when there's scaling.
Attachment #515245 -
Flags: review?(roc)
Assignee | ||
Comment 26•14 years ago
|
||
Attachment #515246 -
Flags: superreview?(roc)
Assignee | ||
Comment 27•14 years ago
|
||
memmove vs. memcpy shouldn't make much of a difference if they're implemented well, but that's worth measuring at some point, especially with android's libc.
Attachment #515248 -
Flags: review?(roc)
Assignee | ||
Comment 28•14 years ago
|
||
I'm not particularly happy with this patch. Suggestions welcome.
Attachment #515249 -
Flags: review?(roc)
Assignee | ||
Comment 29•14 years ago
|
||
I can't think of any reason to keep this around.
Attachment #515250 -
Flags: superreview?(roc)
Assignee | ||
Comment 30•14 years ago
|
||
Should add that I decided against adding buffer-fluffing here. I suspect the cause of the buffer-size jitter is related to the underlying cause of bug 630743. Can investigate fluffing later if needed, it's trivial.
Comment 31•14 years ago
|
||
Comment on attachment 515244 [details] [diff] [review] part 1: Separate the extended draw region and computed draw region so that shadow-layer readback gets the same quadrant as what was drawn We're actually trying to get rid of ExtendForScaling usage in bug 633344, but I think an equivalent problem will still exist since we still need to extend the draw region out. Looks good to me!
Attachment #515244 -
Flags: review?(matt.woodrow+bugzilla) → review+
Attachment #515245 -
Flags: review?(roc) → review+
Attachment #515246 -
Flags: superreview?(roc) → superreview+
+ * |aSourceRect| and the destination rectangle defined by + * |aDestTopLeft| must lie entirely within this surface. + * (XXX should this API be friendlier?) + * + * Return true iff the pixels were successfully moved. Actually ... I think this API should clip the source and destination to the bounds, and should always succeed.
Attachment #515246 -
Flags: superreview+ → superreview-
Comment on attachment 515248 [details] [diff] [review] part 4: Implement MovePixels() for image surfaces + // XXX can memcpy for disjoint dest/source + memmove(dst, src, nBytes); Lose the comment. memmove should internally optimize for disjointness if that helps.
Attachment #515248 -
Flags: review?(roc) → review+
+ // We have to assume here we're dealing with rects that are supposed + // to round to device pixels, or else many other things besides + // pixel moves will be wrong. + src.Round(); + dest.Round(); Maybe we should assert something instead of rounding, then? Maybe we should actually assert that MovePixels is only called for identity resolution?
Attachment #515250 -
Flags: superreview?(roc) → superreview+
Assignee | ||
Comment 35•14 years ago
|
||
(In reply to comment #32) > + * |aSourceRect| and the destination rectangle defined by > + * |aDestTopLeft| must lie entirely within this surface. > + * (XXX should this API be friendlier?) > + * > + * Return true iff the pixels were successfully moved. > > Actually ... I think this API should clip the source and destination to the > bounds, and should always succeed. Sure. (In reply to comment #33) > Comment on attachment 515248 [details] [diff] [review] > part 4: Implement MovePixels() for image surfaces > > + // XXX can memcpy for disjoint dest/source > + memmove(dst, src, nBytes); > > Lose the comment. memmove should internally optimize for disjointness if that > helps. Yes, good impls should. But yeah, that comment isn't going to help anyone. (In reply to comment #34) > + // We have to assume here we're dealing with rects that are supposed > + // to round to device pixels, or else many other things besides > + // pixel moves will be wrong. > + src.Round(); > + dest.Round(); > > Maybe we should assert something instead of rounding, then? Maybe we should > actually assert that MovePixels is only called for identity resolution? Sure, we can assert that the values are within epsilon of whole pixels. I'm pretty sure the cause of bug 630743 will trip these assertions, and indeed I saw some seaming this weekend when test-driving these patches. Not self-copying for non-identity resolution is going to hurt on fennec. There was a quite noticeable perf improvement with these patches and bug 634397. With bug 630743 fixed, I don't think fennec would attempt fractional-device-pixel scrolls. I'm not sure about transformed thebeslayers.
Updated•14 years ago
|
Whiteboard: [needs-review (roc)]
So are you saying that we know these Round() calls are wrong and should not be needed but we need them because the underlying bug is too hard to fix?
Assignee | ||
Comment 37•14 years ago
|
||
These patches need to be updated, they're not awaiting review. (In reply to comment #36) > So are you saying that we know these Round() calls are wrong and should not be > needed but we need them because the underlying bug is too hard to fix? No, I'm saying that the Round() calls should be correct for fennec after bug 630743 and bug 637852 are fixed. I don't know about transformed thebeslayers. We can selectively disable self-copy too for just transformed thebeslayers pretty easily.
Whiteboard: [needs-review (roc)]
Updated•14 years ago
|
Whiteboard: [needs-new-patch]
Assignee | ||
Comment 38•14 years ago
|
||
Attachment #516993 -
Flags: review?(roc)
Assignee | ||
Comment 39•14 years ago
|
||
I like this API a lot better. Thanks!
Attachment #515246 -
Attachment is obsolete: true
Attachment #516994 -
Flags: superreview?(roc)
Assignee | ||
Comment 40•14 years ago
|
||
The icky memmove stuff didn't change, but I'd appreciate a second look at the clip computations.
Attachment #516995 -
Flags: review?(roc)
Assignee | ||
Comment 41•14 years ago
|
||
Attachment #516996 -
Flags: superreview?(roc)
Assignee | ||
Comment 42•14 years ago
|
||
Checks rounding.
Attachment #515249 -
Attachment is obsolete: true
Attachment #515249 -
Flags: review?(roc)
Updated•14 years ago
|
Whiteboard: [needs-new-patch] → [needs-review (roc)]
Reporter | ||
Comment 43•14 years ago
|
||
635035 part 1 now produces black screens for me on Android. Chris, any ideas?
Assignee | ||
Comment 44•14 years ago
|
||
No... works OK for me on desktop, but I haven't tried on device. Are you running a build with other patches applied under this?
Reporter | ||
Comment 45•14 years ago
|
||
No other patches applied, and I was testing on Android. Do you mind seeing if it happens to you too?
Assignee | ||
Comment 46•14 years ago
|
||
I'm not really around right now, but I can look later. Are seeing this on desktop too? Do you have other patches applied above part 1? Are there any pages in particular on which the black screens appear?
Attachment #516993 -
Flags: review?(roc) → review+
Comment on attachment 516994 [details] [diff] [review] part 3: Add gfxASurface::MovePixels() interface and generic impl, v2 + if (!bounds.Intersects(aSourceRect) || !bounds.Intersects(aSourceRect)) { oops? Also I don't think you need this unless you think fully-clipped moves are common. The API is OK though.
Attachment #516994 -
Flags: superreview?(roc) → superreview+
+ long naturalStride = ComputeStride(mSize, mFormat); + if (mStride == naturalStride && dest.width == bounds.width) { Why do we need to check the natural stride here? If there are unused bytes at the end of rows, why can't we just move them? Dropping that check would also let this path work with negative stride, which could be useful. Otherwise looks good.
Attachment #516996 -
Flags: superreview?(roc) → superreview+
Comment on attachment 516996 [details] [diff] [review] part 5: Add a helper to check whether a gfxRect is rounded within a given epsilon Actually aEpsilon should be a double here.
Reporter | ||
Comment 50•14 years ago
|
||
(In reply to comment #46) > I'm not really around right now, but I can look later. > > Are seeing this on desktop too? Do you have other patches applied above part > 1? Are there any pages in particular on which the black screens appear? Like I said in c45, no other patches applied above part 1. Desktop looks fine for me.
Assignee | ||
Comment 51•14 years ago
|
||
(In reply to comment #47) > Comment on attachment 516994 [details] [diff] [review] > part 3: Add gfxASurface::MovePixels() interface and generic impl, v2 > > + if (!bounds.Intersects(aSourceRect) || !bounds.Intersects(aSourceRect)) { > > oops? Also I don't think you need this unless you think fully-clipped moves are > common. Oops! Shouldn't be, can remove. (In reply to comment #48) > + long naturalStride = ComputeStride(mSize, mFormat); > + if (mStride == naturalStride && dest.width == bounds.width) { > > Why do we need to check the natural stride here? If there are unused bytes at > the end of rows, why can't we just move them? No, the surface might be a subimage of another surface, e.g. > Dropping that check would also let this path work with negative stride, which > could be useful. It would be possible to normalize the stride and first/last row before figuring out which path to use. Do you think negative strides are worth optimizing for?
Reporter | ||
Comment 52•14 years ago
|
||
With just these patches applied I see this corruption for Google page flip. Can someone confirm?
Assignee | ||
Comment 53•14 years ago
|
||
Re-nom'ing for 4.x based on bug 637852. We could take this and bug 634397 for 4.0 if we can live with the seaming, but I don't think that's a good idea.
tracking-fennec: 2.0+ → ?
Assignee | ||
Comment 54•14 years ago
|
||
Actually, we need to land part 1 and part 2 for 4.0.
Assignee | ||
Comment 55•14 years ago
|
||
Part 1 and 2 fix bugs that can cause the wrong buffer quadrant to be computed, leading us to paint into the wrong part of the thebeslayerbuffer.
Assignee | ||
Updated•14 years ago
|
Summary: ThebesLayerBuffer can compute the wrong quadrant to draw into with non-identity resolution → ThebesLayerBuffer can compute the wrong quadrant to draw into with non-identity resolution, should support self-copies for image surfaces
Attachment #516995 -
Flags: review?(roc) → review+
Assignee | ||
Comment 58•14 years ago
|
||
(In reply to comment #36) > So are you saying that we know these Round() calls are wrong and should not be > needed but we need them because the underlying bug is too hard to fix? The answer to this ended up being "partly yes, in the 4.0 timeframe", disregard comment 37. I'm leaving a FIXME/bug 637852 breadcrumb.
Reporter | ||
Comment 59•14 years ago
|
||
Could we get comment #52 addressed? Can anyone else repro?
Assignee | ||
Comment 60•14 years ago
|
||
Looking in a bit.
Assignee | ||
Comment 61•14 years ago
|
||
I can repro something like comment 52 on http://fastflip.googlelabs.com/ by pressing the ">" button on the first row of images. The corruption goes away on its own after ~5 seconds. This reminds me a lot of an existing bug I think I saw somewhere, but I don't remember which.
Assignee | ||
Comment 62•14 years ago
|
||
Unsurprisingly, part 6 is the culprit. Might be a bug in MovePixels().
Assignee | ||
Comment 63•14 years ago
|
||
I'm getting "WARNING: Rects don't round to device pixels within precision; glitches likely to follow" when this happens :/. I'll see if there's anything we can do.
Assignee | ||
Comment 64•14 years ago
|
||
Just a dumb typo I made when updating to the new API: if (mBufferRotation == nsIntPoint(0,0)) { nsIntRect srcRect(nsIntPoint(0, 0), mBufferRect.Size()); - nsIntPoint dest = destBufferRect.TopLeft() - mBufferRect.TopLeft(); + nsIntPoint dest = mBufferRect.TopLeft() - destBufferRect.TopLeft(); MovePixels(mBuffer, srcRect, dest, curXRes, curYRes); Ready to land after tryserver'ing.
Assignee | ||
Comment 65•14 years ago
|
||
http://hg.mozilla.org/mozilla-central/rev/439f8db100d7 http://hg.mozilla.org/mozilla-central/rev/5a3f1c4e63c1 http://hg.mozilla.org/mozilla-central/rev/173971a4af7e http://hg.mozilla.org/mozilla-central/rev/d4a93181df15 http://hg.mozilla.org/mozilla-central/rev/4ab41ca945e0 http://hg.mozilla.org/mozilla-central/rev/edf7507120f7 http://hg.mozilla.org/mozilla-central/rev/54f451b29081
Status: NEW → RESOLVED
Closed: 14 years ago
Resolution: --- → FIXED
You need to log in
before you can comment on or make changes to this bug.
Description
•